From 5232afa13d8738d0f50aef5238a82837391c6e49 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Sat, 24 Feb 2024 14:36:57 +0100 Subject: [PATCH] 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. --- Userland/Libraries/LibProtocol/Request.cpp | 16 +++++++++- Userland/Libraries/LibProtocol/Request.h | 9 ++---- .../Libraries/LibProtocol/RequestClient.cpp | 25 ++++++++++------ .../Libraries/LibProtocol/RequestClient.h | 1 + .../RequestServer/ConnectionCache.cpp | 16 +++++----- .../Services/RequestServer/ConnectionCache.h | 30 +++++++++---------- .../RequestServer/ConnectionFromClient.cpp | 16 ++++++---- .../RequestServer/ConnectionFromClient.h | 2 +- .../Services/RequestServer/GeminiProtocol.cpp | 8 +++-- .../Services/RequestServer/GeminiProtocol.h | 2 +- .../Services/RequestServer/GeminiRequest.cpp | 8 ++--- .../Services/RequestServer/GeminiRequest.h | 4 +-- Userland/Services/RequestServer/HttpCommon.h | 14 +++++---- .../Services/RequestServer/HttpProtocol.cpp | 4 +-- .../Services/RequestServer/HttpProtocol.h | 2 +- .../Services/RequestServer/HttpRequest.cpp | 8 ++--- Userland/Services/RequestServer/HttpRequest.h | 4 +-- .../Services/RequestServer/HttpsProtocol.cpp | 4 +-- .../Services/RequestServer/HttpsProtocol.h | 2 +- .../Services/RequestServer/HttpsRequest.cpp | 8 ++--- .../Services/RequestServer/HttpsRequest.h | 4 +-- Userland/Services/RequestServer/Protocol.h | 2 +- Userland/Services/RequestServer/Request.cpp | 7 ++--- Userland/Services/RequestServer/Request.h | 2 +- .../Services/RequestServer/RequestClient.ipc | 1 + .../Services/RequestServer/RequestServer.ipc | 2 +- 26 files changed, 114 insertions(+), 87 deletions(-) diff --git a/Userland/Libraries/LibProtocol/Request.cpp b/Userland/Libraries/LibProtocol/Request.cpp index 325c8b9dc4f..acf8a5032d3 100644 --- a/Userland/Libraries/LibProtocol/Request.cpp +++ b/Userland/Libraries/LibProtocol/Request.cpp @@ -20,12 +20,26 @@ bool Request::stop() return m_client->stop_request({}, *this); } +void Request::set_request_fd(Badge, 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(MUST(Core::File::adopt_fd(fd(), Core::File::OpenMode::Read))); + m_internal_stream_data = make(); 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) { diff --git a/Userland/Libraries/LibProtocol/Request.h b/Userland/Libraries/LibProtocol/Request.h index 9a92f09b16f..c7510135991 100644 --- a/Userland/Libraries/LibProtocol/Request.h +++ b/Userland/Libraries/LibProtocol/Request.h @@ -55,7 +55,7 @@ public: void did_request_certificates(Badge); RefPtr& write_notifier(Badge) { return m_write_notifier; } - void set_request_fd(Badge, int fd) { m_fd = fd; } + void set_request_fd(Badge, int fd); private: explicit Request(RequestClient&, i32 request_id); @@ -73,12 +73,9 @@ private: }; struct InternalStreamData { - InternalStreamData(NonnullOwnPtr stream) - : read_stream(move(stream)) - { - } + InternalStreamData() { } - NonnullOwnPtr read_stream; + OwnPtr read_stream; RefPtr read_notifier; bool success; u32 total_size { 0 }; diff --git a/Userland/Libraries/LibProtocol/RequestClient.cpp b/Userland/Libraries/LibProtocol/RequestClient.cpp index 01206348bf8..a8c297d93bd 100644 --- a/Userland/Libraries/LibProtocol/RequestClient.cpp +++ b/Userland/Libraries/LibProtocol/RequestClient.cpp @@ -29,20 +29,27 @@ RefPtr 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) { if (!m_requests.contains(request.id())) diff --git a/Userland/Libraries/LibProtocol/RequestClient.h b/Userland/Libraries/LibProtocol/RequestClient.h index 720d6abef29..fda544e8711 100644 --- a/Userland/Libraries/LibProtocol/RequestClient.h +++ b/Userland/Libraries/LibProtocol/RequestClient.h @@ -32,6 +32,7 @@ public: bool set_certificate(Badge, Request&, ByteString, ByteString); private: + virtual void request_started(i32, IPC::File const&) override; virtual void request_progress(i32, Optional const&, u64) override; virtual void request_finished(i32, bool, u64) override; virtual void certificate_requested(i32) override; diff --git a/Userland/Services/RequestServer/ConnectionCache.cpp b/Userland/Services/RequestServer/ConnectionCache.cpp index fbbd77d897a..5ac71cdd9a1 100644 --- a/Userland/Services/RequestServer/ConnectionCache.cpp +++ b/Userland/Services/RequestServer/ConnectionCache.cpp @@ -71,13 +71,15 @@ void request_did_finish(URL const& url, Core::Socket const* socket) connection->job_data.fail(Core::NetworkJob::Error::ConnectionFailed); return; } - Core::deferred_invoke([&, url] { - dbgln_if(REQUESTSERVER_DEBUG, "Running next job in queue for connection {} @{}", &connection, connection->socket); - connection->timer.start(); - connection->current_url = url; - connection->job_data = connection->request_queue.take_first(); - connection->socket->set_notifications_enabled(true); - connection->job_data.start(*connection->socket); + + connection->has_started = true; + Core::deferred_invoke([&connection = *connection, url] { + dbgln_if(REQUESTSERVER_DEBUG, "Running next job in queue for connection {}", &connection); + connection.timer.start(); + connection.current_url = url; + connection.job_data = connection.request_queue.take_first(); + connection.socket->set_notifications_enabled(true); + connection.job_data.start(*connection.socket); }); } }; diff --git a/Userland/Services/RequestServer/ConnectionCache.h b/Userland/Services/RequestServer/ConnectionCache.h index 2a3af7da87d..cdfeffe0b8f 100644 --- a/Userland/Services/RequestServer/ConnectionCache.h +++ b/Userland/Services/RequestServer/ConnectionCache.h @@ -248,22 +248,22 @@ decltype(auto) get_or_create_connection(auto& cache, URL const& url, auto job, C auto& connection = *sockets_for_url[index]; if (!connection.has_started) { - if (auto result = recreate_socket_if_needed(connection, url); result.is_error()) { - dbgln("ConnectionCache: request failed to start, failed to make a socket: {}", result.error()); - Core::deferred_invoke([job] { - job->fail(Core::NetworkJob::Error::ConnectionFailed); - }); - return ReturnType { nullptr }; - } - dbgln_if(REQUESTSERVER_DEBUG, "Immediately start request for url {} in {} - {}", url, &connection, connection.socket); + connection.has_started = true; Core::deferred_invoke([&connection, url, job] { - connection.has_started = true; - connection.removal_timer->stop(); - connection.timer.start(); - connection.current_url = url; - connection.job_data = decltype(connection.job_data)::create(job); - connection.socket->set_notifications_enabled(true); - connection.job_data.start(*connection.socket); + if (auto result = recreate_socket_if_needed(connection, url); result.is_error()) { + dbgln("ConnectionCache: request failed to start, failed to make a socket: {}", result.error()); + Core::deferred_invoke([job] { + job->fail(Core::NetworkJob::Error::ConnectionFailed); + }); + } else { + dbgln_if(REQUESTSERVER_DEBUG, "Immediately start request for url {} in {} - {}", url, &connection, connection.socket); + connection.removal_timer->stop(); + connection.timer.start(); + connection.current_url = url; + connection.job_data = decltype(connection.job_data)::create(job); + connection.socket->set_notifications_enabled(true); + connection.job_data.start(*connection.socket); + } }); } else { dbgln_if(REQUESTSERVER_DEBUG, "Enqueue request for URL {} in {} - {}", url, &connection, connection.socket); diff --git a/Userland/Services/RequestServer/ConnectionFromClient.cpp b/Userland/Services/RequestServer/ConnectionFromClient.cpp index 1acb6630d66..d732fe5c12a 100644 --- a/Userland/Services/RequestServer/ConnectionFromClient.cpp +++ b/Userland/Services/RequestServer/ConnectionFromClient.cpp @@ -39,26 +39,30 @@ Messages::RequestServer::IsSupportedProtocolResponse ConnectionFromClient::is_su return supported; } -Messages::RequestServer::StartRequestResponse ConnectionFromClient::start_request(ByteString const& method, URL const& url, HashMap const& request_headers, ByteBuffer const& request_body, Core::ProxyData const& proxy_data) +void ConnectionFromClient::start_request(i32 request_id, ByteString const& method, URL const& url, HashMap const& request_headers, ByteBuffer const& request_body, Core::ProxyData const& proxy_data) { if (!url.is_valid()) { dbgln("StartRequest: Invalid URL requested: '{}'", url); - return { -1, Optional {} }; + (void)post_message(Messages::RequestClient::RequestFinished(request_id, false, 0)); + return; } + auto* protocol = Protocol::find_by_name(url.scheme().to_byte_string()); if (!protocol) { dbgln("StartRequest: No protocol handler for URL: '{}'", url); - return { -1, Optional {} }; + (void)post_message(Messages::RequestClient::RequestFinished(request_id, false, 0)); + return; } - auto request = protocol->start_request(*this, method, url, request_headers, request_body, proxy_data); + auto request = protocol->start_request(request_id, *this, method, url, request_headers, request_body, proxy_data); if (!request) { dbgln("StartRequest: Protocol handler failed to start request: '{}'", url); - return { -1, Optional {} }; + (void)post_message(Messages::RequestClient::RequestFinished(request_id, false, 0)); + return; } auto id = request->id(); auto fd = request->request_fd(); m_requests.set(id, move(request)); - return { id, IPC::File(fd, IPC::File::CloseAfterSending) }; + (void)post_message(Messages::RequestClient::RequestStarted(request_id, IPC::File(fd, IPC::File::CloseAfterSending))); } Messages::RequestServer::StopRequestResponse ConnectionFromClient::stop_request(i32 request_id) diff --git a/Userland/Services/RequestServer/ConnectionFromClient.h b/Userland/Services/RequestServer/ConnectionFromClient.h index 144ace1f987..ead2159e4ff 100644 --- a/Userland/Services/RequestServer/ConnectionFromClient.h +++ b/Userland/Services/RequestServer/ConnectionFromClient.h @@ -32,7 +32,7 @@ private: explicit ConnectionFromClient(NonnullOwnPtr); virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(ByteString const&) override; - virtual Messages::RequestServer::StartRequestResponse start_request(ByteString const&, URL const&, HashMap const&, ByteBuffer const&, Core::ProxyData const&) override; + virtual void start_request(i32 request_id, ByteString const&, URL const&, HashMap const&, ByteBuffer const&, Core::ProxyData const&) override; virtual Messages::RequestServer::StopRequestResponse stop_request(i32) override; virtual Messages::RequestServer::SetCertificateResponse set_certificate(i32, ByteString const&, ByteString const&) override; virtual void ensure_connection(URL const& url, ::RequestServer::CacheLevel const& cache_level) override; diff --git a/Userland/Services/RequestServer/GeminiProtocol.cpp b/Userland/Services/RequestServer/GeminiProtocol.cpp index 60c36b05798..d29f94a1de9 100644 --- a/Userland/Services/RequestServer/GeminiProtocol.cpp +++ b/Userland/Services/RequestServer/GeminiProtocol.cpp @@ -17,7 +17,7 @@ GeminiProtocol::GeminiProtocol() { } -OwnPtr GeminiProtocol::start_request(ConnectionFromClient& client, ByteString const&, const URL& url, HashMap const&, ReadonlyBytes, Core::ProxyData proxy_data) +OwnPtr GeminiProtocol::start_request(i32 request_id, ConnectionFromClient& client, ByteString const&, const URL& url, HashMap const&, ReadonlyBytes, Core::ProxyData proxy_data) { Gemini::GeminiRequest request; request.set_url(url); @@ -28,10 +28,12 @@ OwnPtr GeminiProtocol::start_request(ConnectionFromClient& client, Byte auto output_stream = MUST(Core::File::adopt_fd(pipe_result.value().write_fd, Core::File::OpenMode::Write)); auto job = Gemini::Job::construct(request, *output_stream); - auto protocol_request = GeminiRequest::create_with_job({}, client, *job, move(output_stream)); + auto protocol_request = GeminiRequest::create_with_job({}, client, *job, move(output_stream), request_id); protocol_request->set_request_fd(pipe_result.value().read_fd); - ConnectionCache::get_or_create_connection(ConnectionCache::g_tls_connection_cache, url, job, proxy_data); + Core::EventLoop::current().deferred_invoke([=] { + ConnectionCache::get_or_create_connection(ConnectionCache::g_tls_connection_cache, url, job, proxy_data); + }); return protocol_request; } diff --git a/Userland/Services/RequestServer/GeminiProtocol.h b/Userland/Services/RequestServer/GeminiProtocol.h index 30b6e2ac5b8..421e4bba499 100644 --- a/Userland/Services/RequestServer/GeminiProtocol.h +++ b/Userland/Services/RequestServer/GeminiProtocol.h @@ -15,7 +15,7 @@ public: GeminiProtocol(); virtual ~GeminiProtocol() override = default; - virtual OwnPtr start_request(ConnectionFromClient&, ByteString const& method, const URL&, HashMap const&, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override; + virtual OwnPtr start_request(i32, ConnectionFromClient&, ByteString const& method, const URL&, HashMap const&, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override; }; } diff --git a/Userland/Services/RequestServer/GeminiRequest.cpp b/Userland/Services/RequestServer/GeminiRequest.cpp index 48725b6e900..2adb0f410b3 100644 --- a/Userland/Services/RequestServer/GeminiRequest.cpp +++ b/Userland/Services/RequestServer/GeminiRequest.cpp @@ -12,8 +12,8 @@ namespace RequestServer { -GeminiRequest::GeminiRequest(ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream) - : Request(client, move(output_stream)) +GeminiRequest::GeminiRequest(ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream, i32 request_id) + : Request(client, move(output_stream), request_id) , m_job(move(job)) { m_job->on_finish = [this](bool success) { @@ -57,9 +57,9 @@ GeminiRequest::~GeminiRequest() m_job->cancel(); } -NonnullOwnPtr GeminiRequest::create_with_job(Badge, ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream) +NonnullOwnPtr GeminiRequest::create_with_job(Badge, ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream, i32 request_id) { - return adopt_own(*new GeminiRequest(client, move(job), move(output_stream))); + return adopt_own(*new GeminiRequest(client, move(job), move(output_stream), request_id)); } } diff --git a/Userland/Services/RequestServer/GeminiRequest.h b/Userland/Services/RequestServer/GeminiRequest.h index a8d9a4bdfb2..ca46e371082 100644 --- a/Userland/Services/RequestServer/GeminiRequest.h +++ b/Userland/Services/RequestServer/GeminiRequest.h @@ -16,14 +16,14 @@ namespace RequestServer { class GeminiRequest final : public Request { public: virtual ~GeminiRequest() override; - static NonnullOwnPtr create_with_job(Badge, ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&); + static NonnullOwnPtr create_with_job(Badge, ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&, i32 request_id); Gemini::Job const& job() const { return *m_job; } virtual URL url() const override { return m_job->url(); } private: - explicit GeminiRequest(ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&); + explicit GeminiRequest(ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&, i32 request_id); virtual void set_certificate(ByteString certificate, ByteString key) override; diff --git a/Userland/Services/RequestServer/HttpCommon.h b/Userland/Services/RequestServer/HttpCommon.h index a3885ff85bf..15b7b85d142 100644 --- a/Userland/Services/RequestServer/HttpCommon.h +++ b/Userland/Services/RequestServer/HttpCommon.h @@ -61,7 +61,7 @@ void init(TSelf* self, TJob job) } template -OwnPtr start_request(TBadgedProtocol&& protocol, ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap const& headers, ReadonlyBytes body, TPipeResult&& pipe_result, Core::ProxyData proxy_data = {}) +OwnPtr start_request(TBadgedProtocol&& protocol, i32 request_id, ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap const& headers, ReadonlyBytes body, TPipeResult&& pipe_result, Core::ProxyData proxy_data = {}) { using TJob = typename TBadgedProtocol::Type::JobType; using TRequest = typename TBadgedProtocol::Type::RequestType; @@ -99,13 +99,15 @@ OwnPtr start_request(TBadgedProtocol&& protocol, ConnectionFromClient& auto output_stream = MUST(Core::File::adopt_fd(pipe_result.value().write_fd, Core::File::OpenMode::Write)); auto job = TJob::construct(move(request), *output_stream); - auto protocol_request = TRequest::create_with_job(forward(protocol), client, (TJob&)*job, move(output_stream)); + auto protocol_request = TRequest::create_with_job(forward(protocol), client, (TJob&)*job, move(output_stream), request_id); protocol_request->set_request_fd(pipe_result.value().read_fd); - if constexpr (IsSame) - ConnectionCache::get_or_create_connection(ConnectionCache::g_tls_connection_cache, url, job, proxy_data); - else - ConnectionCache::get_or_create_connection(ConnectionCache::g_tcp_connection_cache, url, job, proxy_data); + Core::EventLoop::current().deferred_invoke([=] { + if constexpr (IsSame) + ConnectionCache::get_or_create_connection(ConnectionCache::g_tls_connection_cache, url, job, proxy_data); + else + ConnectionCache::get_or_create_connection(ConnectionCache::g_tcp_connection_cache, url, job, proxy_data); + }); return protocol_request; } diff --git a/Userland/Services/RequestServer/HttpProtocol.cpp b/Userland/Services/RequestServer/HttpProtocol.cpp index a1480499970..5ffe3f00afd 100644 --- a/Userland/Services/RequestServer/HttpProtocol.cpp +++ b/Userland/Services/RequestServer/HttpProtocol.cpp @@ -22,9 +22,9 @@ HttpProtocol::HttpProtocol() { } -OwnPtr HttpProtocol::start_request(ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data) +OwnPtr HttpProtocol::start_request(i32 request_id, ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data) { - return Detail::start_request(Badge {}, client, method, url, headers, body, get_pipe_for_request(), proxy_data); + return Detail::start_request(Badge {}, request_id, client, method, url, headers, body, get_pipe_for_request(), proxy_data); } } diff --git a/Userland/Services/RequestServer/HttpProtocol.h b/Userland/Services/RequestServer/HttpProtocol.h index 212087ac4f7..bfa9d8064c2 100644 --- a/Userland/Services/RequestServer/HttpProtocol.h +++ b/Userland/Services/RequestServer/HttpProtocol.h @@ -27,7 +27,7 @@ public: HttpProtocol(); ~HttpProtocol() override = default; - virtual OwnPtr start_request(ConnectionFromClient&, ByteString const& method, const URL&, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override; + virtual OwnPtr start_request(i32, ConnectionFromClient&, ByteString const& method, const URL&, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override; }; } diff --git a/Userland/Services/RequestServer/HttpRequest.cpp b/Userland/Services/RequestServer/HttpRequest.cpp index 0249650c3d9..28cae8c3a04 100644 --- a/Userland/Services/RequestServer/HttpRequest.cpp +++ b/Userland/Services/RequestServer/HttpRequest.cpp @@ -11,8 +11,8 @@ namespace RequestServer { -HttpRequest::HttpRequest(ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream) - : Request(client, move(output_stream)) +HttpRequest::HttpRequest(ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream, i32 request_id) + : Request(client, move(output_stream), request_id) , m_job(job) { Detail::init(this, job); @@ -25,9 +25,9 @@ HttpRequest::~HttpRequest() m_job->cancel(); } -NonnullOwnPtr HttpRequest::create_with_job(Badge&&, ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream) +NonnullOwnPtr HttpRequest::create_with_job(Badge&&, ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream, i32 request_id) { - return adopt_own(*new HttpRequest(client, move(job), move(output_stream))); + return adopt_own(*new HttpRequest(client, move(job), move(output_stream), request_id)); } } diff --git a/Userland/Services/RequestServer/HttpRequest.h b/Userland/Services/RequestServer/HttpRequest.h index 6833e74d6c5..f91527820aa 100644 --- a/Userland/Services/RequestServer/HttpRequest.h +++ b/Userland/Services/RequestServer/HttpRequest.h @@ -17,7 +17,7 @@ namespace RequestServer { class HttpRequest final : public Request { public: virtual ~HttpRequest() override; - static NonnullOwnPtr create_with_job(Badge&&, ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&); + static NonnullOwnPtr create_with_job(Badge&&, ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&, i32); HTTP::Job& job() { return m_job; } HTTP::Job const& job() const { return m_job; } @@ -25,7 +25,7 @@ public: virtual URL url() const override { return m_job->url(); } private: - explicit HttpRequest(ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&); + explicit HttpRequest(ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&, i32); NonnullRefPtr m_job; }; diff --git a/Userland/Services/RequestServer/HttpsProtocol.cpp b/Userland/Services/RequestServer/HttpsProtocol.cpp index 6d9ea5a5311..49c017132f3 100644 --- a/Userland/Services/RequestServer/HttpsProtocol.cpp +++ b/Userland/Services/RequestServer/HttpsProtocol.cpp @@ -22,9 +22,9 @@ HttpsProtocol::HttpsProtocol() { } -OwnPtr HttpsProtocol::start_request(ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data) +OwnPtr HttpsProtocol::start_request(i32 request_id, ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data) { - return Detail::start_request(Badge {}, client, method, url, headers, body, get_pipe_for_request(), proxy_data); + return Detail::start_request(Badge {}, request_id, client, method, url, headers, body, get_pipe_for_request(), proxy_data); } } diff --git a/Userland/Services/RequestServer/HttpsProtocol.h b/Userland/Services/RequestServer/HttpsProtocol.h index 9199d396157..00afb034553 100644 --- a/Userland/Services/RequestServer/HttpsProtocol.h +++ b/Userland/Services/RequestServer/HttpsProtocol.h @@ -27,7 +27,7 @@ public: HttpsProtocol(); ~HttpsProtocol() override = default; - virtual OwnPtr start_request(ConnectionFromClient&, ByteString const& method, const URL&, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override; + virtual OwnPtr start_request(i32, ConnectionFromClient&, ByteString const& method, const URL&, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override; }; } diff --git a/Userland/Services/RequestServer/HttpsRequest.cpp b/Userland/Services/RequestServer/HttpsRequest.cpp index 914714ee6ed..fd211065cc9 100644 --- a/Userland/Services/RequestServer/HttpsRequest.cpp +++ b/Userland/Services/RequestServer/HttpsRequest.cpp @@ -11,8 +11,8 @@ namespace RequestServer { -HttpsRequest::HttpsRequest(ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream) - : Request(client, move(output_stream)) +HttpsRequest::HttpsRequest(ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream, i32 request_id) + : Request(client, move(output_stream), request_id) , m_job(job) { Detail::init(this, job); @@ -30,9 +30,9 @@ HttpsRequest::~HttpsRequest() m_job->cancel(); } -NonnullOwnPtr HttpsRequest::create_with_job(Badge&&, ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream) +NonnullOwnPtr HttpsRequest::create_with_job(Badge&&, ConnectionFromClient& client, NonnullRefPtr job, NonnullOwnPtr&& output_stream, i32 request_id) { - return adopt_own(*new HttpsRequest(client, move(job), move(output_stream))); + return adopt_own(*new HttpsRequest(client, move(job), move(output_stream), request_id)); } } diff --git a/Userland/Services/RequestServer/HttpsRequest.h b/Userland/Services/RequestServer/HttpsRequest.h index 8539836f91c..eff62c607bd 100644 --- a/Userland/Services/RequestServer/HttpsRequest.h +++ b/Userland/Services/RequestServer/HttpsRequest.h @@ -16,7 +16,7 @@ namespace RequestServer { class HttpsRequest final : public Request { public: virtual ~HttpsRequest() override; - static NonnullOwnPtr create_with_job(Badge&&, ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&); + static NonnullOwnPtr create_with_job(Badge&&, ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&, i32); HTTP::HttpsJob& job() { return m_job; } HTTP::HttpsJob const& job() const { return m_job; } @@ -24,7 +24,7 @@ public: virtual URL url() const override { return m_job->url(); } private: - explicit HttpsRequest(ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&); + explicit HttpsRequest(ConnectionFromClient&, NonnullRefPtr, NonnullOwnPtr&&, i32); virtual void set_certificate(ByteString certificate, ByteString key) override; diff --git a/Userland/Services/RequestServer/Protocol.h b/Userland/Services/RequestServer/Protocol.h index a093d1c41df..73795643496 100644 --- a/Userland/Services/RequestServer/Protocol.h +++ b/Userland/Services/RequestServer/Protocol.h @@ -18,7 +18,7 @@ public: virtual ~Protocol(); ByteString const& name() const { return m_name; } - virtual OwnPtr start_request(ConnectionFromClient&, ByteString const& method, const URL&, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) = 0; + virtual OwnPtr start_request(i32, ConnectionFromClient&, ByteString const& method, const URL&, HashMap const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) = 0; static Protocol* find_by_name(ByteString const&); diff --git a/Userland/Services/RequestServer/Request.cpp b/Userland/Services/RequestServer/Request.cpp index f549b59b18c..f9663a0c777 100644 --- a/Userland/Services/RequestServer/Request.cpp +++ b/Userland/Services/RequestServer/Request.cpp @@ -9,12 +9,9 @@ namespace RequestServer { -// FIXME: What about rollover? -static i32 s_next_id = 1; - -Request::Request(ConnectionFromClient& client, NonnullOwnPtr&& output_stream) +Request::Request(ConnectionFromClient& client, NonnullOwnPtr&& output_stream, i32 request_id) : m_client(client) - , m_id(s_next_id++) + , m_id(request_id) , m_output_stream(move(output_stream)) { } diff --git a/Userland/Services/RequestServer/Request.h b/Userland/Services/RequestServer/Request.h index 41df486e85f..364ed1219e8 100644 --- a/Userland/Services/RequestServer/Request.h +++ b/Userland/Services/RequestServer/Request.h @@ -43,7 +43,7 @@ public: Core::File const& output_stream() const { return *m_output_stream; } protected: - explicit Request(ConnectionFromClient&, NonnullOwnPtr&&); + explicit Request(ConnectionFromClient&, NonnullOwnPtr&&, i32 request_id); private: ConnectionFromClient& m_client; diff --git a/Userland/Services/RequestServer/RequestClient.ipc b/Userland/Services/RequestServer/RequestClient.ipc index 124abd933b1..408d5295be5 100644 --- a/Userland/Services/RequestServer/RequestClient.ipc +++ b/Userland/Services/RequestServer/RequestClient.ipc @@ -2,6 +2,7 @@ endpoint RequestClient { + request_started(i32 request_id, IPC::File fd) =| request_progress(i32 request_id, Optional total_size, u64 downloaded_size) =| request_finished(i32 request_id, bool success, u64 total_size) =| headers_became_available(i32 request_id, HashMap response_headers, Optional status_code) =| diff --git a/Userland/Services/RequestServer/RequestServer.ipc b/Userland/Services/RequestServer/RequestServer.ipc index 8c256682b53..01225f8041e 100644 --- a/Userland/Services/RequestServer/RequestServer.ipc +++ b/Userland/Services/RequestServer/RequestServer.ipc @@ -6,7 +6,7 @@ endpoint RequestServer // Test if a specific protocol is supported, e.g "http" is_supported_protocol(ByteString protocol) => (bool supported) - start_request(ByteString method, URL url, HashMap request_headers, ByteBuffer request_body, Core::ProxyData proxy_data) => (i32 request_id, Optional response_fd) + start_request(i32 request_id, ByteString method, URL url, HashMap request_headers, ByteBuffer request_body, Core::ProxyData proxy_data) =| stop_request(i32 request_id) => (bool success) set_certificate(i32 request_id, ByteString certificate, ByteString key) => (bool success)