1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 12:57:35 +00:00

RequestServer+LibProtocol: Make starting requests fully async

This makes it so the clients don't have to wait for RS to become
responsive, potentially allowing them to do other things while RS
handles the connections.
Fixes #23306.
This commit is contained in:
Ali Mohammad Pur 2024-02-24 14:36:57 +01:00 committed by Andreas Kling
parent 18d26142f0
commit 5232afa13d
26 changed files with 114 additions and 87 deletions

View file

@ -20,12 +20,26 @@ bool Request::stop()
return m_client->stop_request({}, *this);
}
void Request::set_request_fd(Badge<Protocol::RequestClient>, int fd)
{
VERIFY(m_fd == -1);
m_fd = fd;
auto notifier = Core::Notifier::construct(fd, Core::Notifier::Type::Read);
auto stream = MUST(Core::File::adopt_fd(fd, Core::File::OpenMode::Read));
notifier->on_activation = move(m_internal_stream_data->read_notifier->on_activation);
m_internal_stream_data->read_notifier = move(notifier);
m_internal_stream_data->read_stream = move(stream);
}
void Request::stream_into(Stream& stream)
{
VERIFY(!m_internal_stream_data);
m_internal_stream_data = make<InternalStreamData>(MUST(Core::File::adopt_fd(fd(), Core::File::OpenMode::Read)));
m_internal_stream_data = make<InternalStreamData>();
m_internal_stream_data->read_notifier = Core::Notifier::construct(fd(), Core::Notifier::Type::Read);
if (fd() != -1)
m_internal_stream_data->read_stream = MUST(Core::File::adopt_fd(fd(), Core::File::OpenMode::Read));
auto user_on_finish = move(on_finish);
on_finish = [this](auto success, auto total_size) {

View file

@ -55,7 +55,7 @@ public:
void did_request_certificates(Badge<RequestClient>);
RefPtr<Core::Notifier>& write_notifier(Badge<RequestClient>) { return m_write_notifier; }
void set_request_fd(Badge<RequestClient>, int fd) { m_fd = fd; }
void set_request_fd(Badge<RequestClient>, int fd);
private:
explicit Request(RequestClient&, i32 request_id);
@ -73,12 +73,9 @@ private:
};
struct InternalStreamData {
InternalStreamData(NonnullOwnPtr<Stream> stream)
: read_stream(move(stream))
{
}
InternalStreamData() { }
NonnullOwnPtr<Stream> read_stream;
OwnPtr<Stream> read_stream;
RefPtr<Core::Notifier> read_notifier;
bool success;
u32 total_size { 0 };

View file

@ -29,20 +29,27 @@ RefPtr<Request> RequestClient::start_request(ByteString const& method, URL const
if (body_result.is_error())
return nullptr;
auto maybe_response = IPCProxy::try_start_request(method, url, headers_or_error.release_value(), body_result.release_value(), proxy_data);
if (maybe_response.is_error())
return nullptr;
auto response = maybe_response.release_value();
auto request_id = response.request_id();
if (request_id < 0 || !response.response_fd().has_value())
return nullptr;
auto response_fd = response.response_fd().value().take_fd();
static i32 s_next_request_id = 0;
auto request_id = s_next_request_id++;
IPCProxy::async_start_request(request_id, method, url, headers_or_error.release_value(), body_result.release_value(), proxy_data);
auto request = Request::create_from_id({}, *this, request_id);
request->set_request_fd({}, response_fd);
m_requests.set(request_id, request);
return request;
}
void RequestClient::request_started(i32 request_id, IPC::File const& response_file)
{
auto request = m_requests.get(request_id);
if (!request.has_value()) {
warnln("Received response for non-existent request {}", request_id);
return;
}
auto response_fd = response_file.take_fd();
request.value()->set_request_fd({}, response_fd);
}
bool RequestClient::stop_request(Badge<Request>, Request& request)
{
if (!m_requests.contains(request.id()))

View file

@ -32,6 +32,7 @@ public:
bool set_certificate(Badge<Request>, Request&, ByteString, ByteString);
private:
virtual void request_started(i32, IPC::File const&) override;
virtual void request_progress(i32, Optional<u64> const&, u64) override;
virtual void request_finished(i32, bool, u64) override;
virtual void certificate_requested(i32) override;