Skip to content

Commit

Permalink
ProtocolServer: Avoid blocking all downloads when client stops reading
Browse files Browse the repository at this point in the history
  • Loading branch information
alimpfard authored and awesomekling committed Dec 31, 2020
1 parent 83fed3f commit 2568a93
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 28 deletions.
8 changes: 5 additions & 3 deletions Libraries/LibGemini/Job.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,12 @@ void Job::finish_up()
m_state = State::Finished;
flush_received_buffers();
if (m_received_size != 0) {
// FIXME: What do we do? ignore it?
// "Transmission failed" is not strictly correct, but let's roll with it for now.
// We have to wait for the client to consume all the downloaded data
// before we can actually call `did_finish`. in a normal flow, this should
// never be hit since the client is reading as we are writing, unless there
// are too many concurrent downloads going on.
deferred_invoke([this](auto&) {
did_fail(Error::TransmissionFailed);
finish_up();
});
return;
}
Expand Down
8 changes: 5 additions & 3 deletions Libraries/LibHTTP/Job.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,12 @@ void Job::finish_up()

flush_received_buffers();
if (m_buffered_size != 0) {
// FIXME: What do we do? ignore it?
// "Transmission failed" is not strictly correct, but let's roll with it for now.
// We have to wait for the client to consume all the downloaded data
// before we can actually call `did_finish`. in a normal flow, this should
// never be hit since the client is reading as we are writing, unless there
// are too many concurrent downloads going on.
deferred_invoke([this](auto&) {
did_fail(Error::TransmissionFailed);
finish_up();
});
return;
}
Expand Down
13 changes: 6 additions & 7 deletions Services/ProtocolServer/GeminiProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <LibGemini/GeminiRequest.h>
#include <ProtocolServer/GeminiDownload.h>
#include <ProtocolServer/GeminiProtocol.h>
#include <fcntl.h>

namespace ProtocolServer {

Expand All @@ -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;
}
Expand Down
12 changes: 4 additions & 8 deletions Services/ProtocolServer/HttpProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include <LibHTTP/HttpRequest.h>
#include <ProtocolServer/HttpDownload.h>
#include <ProtocolServer/HttpProtocol.h>
#include <fcntl.h>

namespace ProtocolServer {

Expand All @@ -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;
}
Expand Down
12 changes: 5 additions & 7 deletions Services/ProtocolServer/HttpsProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
14 changes: 14 additions & 0 deletions Services/ProtocolServer/Protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

#include <AK/HashMap.h>
#include <ProtocolServer/Protocol.h>
#include <fcntl.h>
#include <string.h>

namespace ProtocolServer {

Expand All @@ -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] };
}

}
6 changes: 6 additions & 0 deletions Services/ProtocolServer/Protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#pragma once

#include <AK/RefPtr.h>
#include <AK/Result.h>
#include <AK/URL.h>
#include <ProtocolServer/Forward.h>

Expand All @@ -43,6 +44,11 @@ class Protocol {

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;
Expand Down

0 comments on commit 2568a93

Please sign in to comment.