summaryrefslogtreecommitdiff
path: root/Services/ProtocolServer
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-12-31 01:42:44 +0330
committerAndreas Kling <kling@serenityos.org>2020-12-31 16:57:09 +0100
commit2568a93b5dd29d2b06d613a4ece502ee696f189a (patch)
treee3d7853f2327a541ef3deec7ffacf1c8cb36353b /Services/ProtocolServer
parent83fed3fd5de71c0eed7390a3cee3de6627bec3bd (diff)
downloadserenity-2568a93b5dd29d2b06d613a4ece502ee696f189a.zip
ProtocolServer: Avoid blocking all downloads when client stops reading
Fixes #4668.
Diffstat (limited to 'Services/ProtocolServer')
-rw-r--r--Services/ProtocolServer/GeminiProtocol.cpp13
-rw-r--r--Services/ProtocolServer/HttpProtocol.cpp12
-rw-r--r--Services/ProtocolServer/HttpsProtocol.cpp12
-rw-r--r--Services/ProtocolServer/Protocol.cpp14
-rw-r--r--Services/ProtocolServer/Protocol.h6
5 files changed, 35 insertions, 22 deletions
diff --git a/Services/ProtocolServer/GeminiProtocol.cpp b/Services/ProtocolServer/GeminiProtocol.cpp
index ff4380de7f..8bf748a50c 100644
--- a/Services/ProtocolServer/GeminiProtocol.cpp
+++ b/Services/ProtocolServer/GeminiProtocol.cpp
@@ -28,6 +28,7 @@
#include <LibGemini/GeminiRequest.h>
#include <ProtocolServer/GeminiDownload.h>
#include <ProtocolServer/GeminiProtocol.h>
+#include <fcntl.h>
namespace ProtocolServer {
@@ -45,17 +46,15 @@ OwnPtr<Download> GeminiProtocol::start_download(ClientConnection& client, const
Gemini::GeminiRequest request;
request.set_url(url);
- int fd_pair[2] { 0 };
- if (pipe(fd_pair) != 0) {
- auto saved_errno = errno;
- dbgln("Protocol: pipe() failed: {}", strerror(saved_errno));
+ auto pipe_result = get_pipe_for_download();
+ if (pipe_result.is_error())
return nullptr;
- }
- auto output_stream = make<OutputFileStream>(fd_pair[1]);
+
+ auto output_stream = make<OutputFileStream>(pipe_result.value().write_fd);
output_stream->make_unbuffered();
auto job = Gemini::GeminiJob::construct(request, *output_stream);
auto download = GeminiDownload::create_with_job({}, client, (Gemini::GeminiJob&)*job, move(output_stream));
- download->set_download_fd(fd_pair[0]);
+ download->set_download_fd(pipe_result.value().read_fd);
job->start();
return download;
}
diff --git a/Services/ProtocolServer/HttpProtocol.cpp b/Services/ProtocolServer/HttpProtocol.cpp
index e8c7a3203c..75c7abc1f8 100644
--- a/Services/ProtocolServer/HttpProtocol.cpp
+++ b/Services/ProtocolServer/HttpProtocol.cpp
@@ -28,7 +28,6 @@
#include <LibHTTP/HttpRequest.h>
#include <ProtocolServer/HttpDownload.h>
#include <ProtocolServer/HttpProtocol.h>
-#include <fcntl.h>
namespace ProtocolServer {
@@ -52,18 +51,15 @@ OwnPtr<Download> HttpProtocol::start_download(ClientConnection& client, const St
request.set_headers(headers);
request.set_body(body);
- int fd_pair[2] { 0 };
- if (pipe(fd_pair) != 0) {
- auto saved_errno = errno;
- dbgln("Protocol: pipe() failed: {}", strerror(saved_errno));
+ auto pipe_result = get_pipe_for_download();
+ if (pipe_result.is_error())
return nullptr;
- }
- auto output_stream = make<OutputFileStream>(fd_pair[1]);
+ auto output_stream = make<OutputFileStream>(pipe_result.value().write_fd);
output_stream->make_unbuffered();
auto job = HTTP::HttpJob::construct(request, *output_stream);
auto download = HttpDownload::create_with_job({}, client, (HTTP::HttpJob&)*job, move(output_stream));
- download->set_download_fd(fd_pair[0]);
+ download->set_download_fd(pipe_result.value().read_fd);
job->start();
return download;
}
diff --git a/Services/ProtocolServer/HttpsProtocol.cpp b/Services/ProtocolServer/HttpsProtocol.cpp
index e34ff32422..9979f0e610 100644
--- a/Services/ProtocolServer/HttpsProtocol.cpp
+++ b/Services/ProtocolServer/HttpsProtocol.cpp
@@ -51,17 +51,15 @@ OwnPtr<Download> HttpsProtocol::start_download(ClientConnection& client, const S
request.set_headers(headers);
request.set_body(body);
- int fd_pair[2] { 0 };
- if (pipe(fd_pair) != 0) {
- auto saved_errno = errno;
- dbgln("Protocol: pipe() failed: {}", strerror(saved_errno));
+ auto pipe_result = get_pipe_for_download();
+ if (pipe_result.is_error())
return nullptr;
- }
- auto output_stream = make<OutputFileStream>(fd_pair[1]);
+
+ auto output_stream = make<OutputFileStream>(pipe_result.value().write_fd);
output_stream->make_unbuffered();
auto job = HTTP::HttpsJob::construct(request, *output_stream);
auto download = HttpsDownload::create_with_job({}, client, (HTTP::HttpsJob&)*job, move(output_stream));
- download->set_download_fd(fd_pair[0]);
+ download->set_download_fd(pipe_result.value().read_fd);
job->start();
return download;
}
diff --git a/Services/ProtocolServer/Protocol.cpp b/Services/ProtocolServer/Protocol.cpp
index de7d74b269..ee8248dfef 100644
--- a/Services/ProtocolServer/Protocol.cpp
+++ b/Services/ProtocolServer/Protocol.cpp
@@ -26,6 +26,8 @@
#include <AK/HashMap.h>
#include <ProtocolServer/Protocol.h>
+#include <fcntl.h>
+#include <string.h>
namespace ProtocolServer {
@@ -50,4 +52,16 @@ Protocol::~Protocol()
ASSERT_NOT_REACHED();
}
+Result<Protocol::Pipe, String> Protocol::get_pipe_for_download()
+{
+ int fd_pair[2] { 0 };
+ if (pipe(fd_pair) != 0) {
+ auto saved_errno = errno;
+ dbgln("Protocol: pipe() failed: {}", strerror(saved_errno));
+ return String { strerror(saved_errno) };
+ }
+ fcntl(fd_pair[1], F_SETFL, fcntl(fd_pair[1], F_GETFL) | O_NONBLOCK);
+ return Pipe { fd_pair[0], fd_pair[1] };
+}
+
}
diff --git a/Services/ProtocolServer/Protocol.h b/Services/ProtocolServer/Protocol.h
index 609362f548..89db931afb 100644
--- a/Services/ProtocolServer/Protocol.h
+++ b/Services/ProtocolServer/Protocol.h
@@ -27,6 +27,7 @@
#pragma once
#include <AK/RefPtr.h>
+#include <AK/Result.h>
#include <AK/URL.h>
#include <ProtocolServer/Forward.h>
@@ -43,6 +44,11 @@ public:
protected:
explicit Protocol(const String& name);
+ struct Pipe {
+ int read_fd { -1 };
+ int write_fd { -1 };
+ };
+ static Result<Pipe, String> get_pipe_for_download();
private:
String m_name;