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
Notes: sideshowbarker 2024-07-17 01:28:15 +09:00
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;

View File

@ -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);
});
}
};

View File

@ -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);

View File

@ -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<ByteString, ByteString> 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<ByteString, ByteString> 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<IPC::File> {} };
(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<IPC::File> {} };
(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<IPC::File> {} };
(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)

View File

@ -32,7 +32,7 @@ private:
explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>);
virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(ByteString const&) override;
virtual Messages::RequestServer::StartRequestResponse start_request(ByteString const&, URL const&, HashMap<ByteString, ByteString> const&, ByteBuffer const&, Core::ProxyData const&) override;
virtual void start_request(i32 request_id, ByteString const&, URL const&, HashMap<ByteString, ByteString> 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;

View File

@ -17,7 +17,7 @@ GeminiProtocol::GeminiProtocol()
{
}
OwnPtr<Request> GeminiProtocol::start_request(ConnectionFromClient& client, ByteString const&, const URL& url, HashMap<ByteString, ByteString> const&, ReadonlyBytes, Core::ProxyData proxy_data)
OwnPtr<Request> GeminiProtocol::start_request(i32 request_id, ConnectionFromClient& client, ByteString const&, const URL& url, HashMap<ByteString, ByteString> const&, ReadonlyBytes, Core::ProxyData proxy_data)
{
Gemini::GeminiRequest request;
request.set_url(url);
@ -28,10 +28,12 @@ OwnPtr<Request> 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;
}

View File

@ -15,7 +15,7 @@ public:
GeminiProtocol();
virtual ~GeminiProtocol() override = default;
virtual OwnPtr<Request> start_request(ConnectionFromClient&, ByteString const& method, const URL&, HashMap<ByteString, ByteString> const&, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override;
virtual OwnPtr<Request> start_request(i32, ConnectionFromClient&, ByteString const& method, const URL&, HashMap<ByteString, ByteString> const&, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override;
};
}

View File

@ -12,8 +12,8 @@
namespace RequestServer {
GeminiRequest::GeminiRequest(ConnectionFromClient& client, NonnullRefPtr<Gemini::Job> job, NonnullOwnPtr<Core::File>&& output_stream)
: Request(client, move(output_stream))
GeminiRequest::GeminiRequest(ConnectionFromClient& client, NonnullRefPtr<Gemini::Job> job, NonnullOwnPtr<Core::File>&& 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> GeminiRequest::create_with_job(Badge<GeminiProtocol>, ConnectionFromClient& client, NonnullRefPtr<Gemini::Job> job, NonnullOwnPtr<Core::File>&& output_stream)
NonnullOwnPtr<GeminiRequest> GeminiRequest::create_with_job(Badge<GeminiProtocol>, ConnectionFromClient& client, NonnullRefPtr<Gemini::Job> job, NonnullOwnPtr<Core::File>&& 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));
}
}

View File

@ -16,14 +16,14 @@ namespace RequestServer {
class GeminiRequest final : public Request {
public:
virtual ~GeminiRequest() override;
static NonnullOwnPtr<GeminiRequest> create_with_job(Badge<GeminiProtocol>, ConnectionFromClient&, NonnullRefPtr<Gemini::Job>, NonnullOwnPtr<Core::File>&&);
static NonnullOwnPtr<GeminiRequest> create_with_job(Badge<GeminiProtocol>, ConnectionFromClient&, NonnullRefPtr<Gemini::Job>, NonnullOwnPtr<Core::File>&&, 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<Gemini::Job>, NonnullOwnPtr<Core::File>&&);
explicit GeminiRequest(ConnectionFromClient&, NonnullRefPtr<Gemini::Job>, NonnullOwnPtr<Core::File>&&, i32 request_id);
virtual void set_certificate(ByteString certificate, ByteString key) override;

View File

@ -61,7 +61,7 @@ void init(TSelf* self, TJob job)
}
template<typename TBadgedProtocol, typename TPipeResult>
OwnPtr<Request> start_request(TBadgedProtocol&& protocol, ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, TPipeResult&& pipe_result, Core::ProxyData proxy_data = {})
OwnPtr<Request> start_request(TBadgedProtocol&& protocol, i32 request_id, ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap<ByteString, ByteString> 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<Request> 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<TBadgedProtocol>(protocol), client, (TJob&)*job, move(output_stream));
auto protocol_request = TRequest::create_with_job(forward<TBadgedProtocol>(protocol), client, (TJob&)*job, move(output_stream), request_id);
protocol_request->set_request_fd(pipe_result.value().read_fd);
if constexpr (IsSame<typename TBadgedProtocol::Type, HttpsProtocol>)
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<typename TBadgedProtocol::Type, HttpsProtocol>)
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;
}

View File

@ -22,9 +22,9 @@ HttpProtocol::HttpProtocol()
{
}
OwnPtr<Request> HttpProtocol::start_request(ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data)
OwnPtr<Request> HttpProtocol::start_request(i32 request_id, ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data)
{
return Detail::start_request(Badge<HttpProtocol> {}, client, method, url, headers, body, get_pipe_for_request(), proxy_data);
return Detail::start_request(Badge<HttpProtocol> {}, request_id, client, method, url, headers, body, get_pipe_for_request(), proxy_data);
}
}

View File

@ -27,7 +27,7 @@ public:
HttpProtocol();
~HttpProtocol() override = default;
virtual OwnPtr<Request> start_request(ConnectionFromClient&, ByteString const& method, const URL&, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override;
virtual OwnPtr<Request> start_request(i32, ConnectionFromClient&, ByteString const& method, const URL&, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override;
};
}

View File

@ -11,8 +11,8 @@
namespace RequestServer {
HttpRequest::HttpRequest(ConnectionFromClient& client, NonnullRefPtr<HTTP::Job> job, NonnullOwnPtr<Core::File>&& output_stream)
: Request(client, move(output_stream))
HttpRequest::HttpRequest(ConnectionFromClient& client, NonnullRefPtr<HTTP::Job> job, NonnullOwnPtr<Core::File>&& 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> HttpRequest::create_with_job(Badge<HttpProtocol>&&, ConnectionFromClient& client, NonnullRefPtr<HTTP::Job> job, NonnullOwnPtr<Core::File>&& output_stream)
NonnullOwnPtr<HttpRequest> HttpRequest::create_with_job(Badge<HttpProtocol>&&, ConnectionFromClient& client, NonnullRefPtr<HTTP::Job> job, NonnullOwnPtr<Core::File>&& 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));
}
}

View File

@ -17,7 +17,7 @@ namespace RequestServer {
class HttpRequest final : public Request {
public:
virtual ~HttpRequest() override;
static NonnullOwnPtr<HttpRequest> create_with_job(Badge<HttpProtocol>&&, ConnectionFromClient&, NonnullRefPtr<HTTP::Job>, NonnullOwnPtr<Core::File>&&);
static NonnullOwnPtr<HttpRequest> create_with_job(Badge<HttpProtocol>&&, ConnectionFromClient&, NonnullRefPtr<HTTP::Job>, NonnullOwnPtr<Core::File>&&, 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<HTTP::Job>, NonnullOwnPtr<Core::File>&&);
explicit HttpRequest(ConnectionFromClient&, NonnullRefPtr<HTTP::Job>, NonnullOwnPtr<Core::File>&&, i32);
NonnullRefPtr<HTTP::Job> m_job;
};

View File

@ -22,9 +22,9 @@ HttpsProtocol::HttpsProtocol()
{
}
OwnPtr<Request> HttpsProtocol::start_request(ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data)
OwnPtr<Request> HttpsProtocol::start_request(i32 request_id, ConnectionFromClient& client, ByteString const& method, const URL& url, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data)
{
return Detail::start_request(Badge<HttpsProtocol> {}, client, method, url, headers, body, get_pipe_for_request(), proxy_data);
return Detail::start_request(Badge<HttpsProtocol> {}, request_id, client, method, url, headers, body, get_pipe_for_request(), proxy_data);
}
}

View File

@ -27,7 +27,7 @@ public:
HttpsProtocol();
~HttpsProtocol() override = default;
virtual OwnPtr<Request> start_request(ConnectionFromClient&, ByteString const& method, const URL&, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override;
virtual OwnPtr<Request> start_request(i32, ConnectionFromClient&, ByteString const& method, const URL&, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override;
};
}

View File

@ -11,8 +11,8 @@
namespace RequestServer {
HttpsRequest::HttpsRequest(ConnectionFromClient& client, NonnullRefPtr<HTTP::HttpsJob> job, NonnullOwnPtr<Core::File>&& output_stream)
: Request(client, move(output_stream))
HttpsRequest::HttpsRequest(ConnectionFromClient& client, NonnullRefPtr<HTTP::HttpsJob> job, NonnullOwnPtr<Core::File>&& 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> HttpsRequest::create_with_job(Badge<HttpsProtocol>&&, ConnectionFromClient& client, NonnullRefPtr<HTTP::HttpsJob> job, NonnullOwnPtr<Core::File>&& output_stream)
NonnullOwnPtr<HttpsRequest> HttpsRequest::create_with_job(Badge<HttpsProtocol>&&, ConnectionFromClient& client, NonnullRefPtr<HTTP::HttpsJob> job, NonnullOwnPtr<Core::File>&& 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));
}
}

View File

@ -16,7 +16,7 @@ namespace RequestServer {
class HttpsRequest final : public Request {
public:
virtual ~HttpsRequest() override;
static NonnullOwnPtr<HttpsRequest> create_with_job(Badge<HttpsProtocol>&&, ConnectionFromClient&, NonnullRefPtr<HTTP::HttpsJob>, NonnullOwnPtr<Core::File>&&);
static NonnullOwnPtr<HttpsRequest> create_with_job(Badge<HttpsProtocol>&&, ConnectionFromClient&, NonnullRefPtr<HTTP::HttpsJob>, NonnullOwnPtr<Core::File>&&, 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<HTTP::HttpsJob>, NonnullOwnPtr<Core::File>&&);
explicit HttpsRequest(ConnectionFromClient&, NonnullRefPtr<HTTP::HttpsJob>, NonnullOwnPtr<Core::File>&&, i32);
virtual void set_certificate(ByteString certificate, ByteString key) override;

View File

@ -18,7 +18,7 @@ public:
virtual ~Protocol();
ByteString const& name() const { return m_name; }
virtual OwnPtr<Request> start_request(ConnectionFromClient&, ByteString const& method, const URL&, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) = 0;
virtual OwnPtr<Request> start_request(i32, ConnectionFromClient&, ByteString const& method, const URL&, HashMap<ByteString, ByteString> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) = 0;
static Protocol* find_by_name(ByteString const&);

View File

@ -9,12 +9,9 @@
namespace RequestServer {
// FIXME: What about rollover?
static i32 s_next_id = 1;
Request::Request(ConnectionFromClient& client, NonnullOwnPtr<Core::File>&& output_stream)
Request::Request(ConnectionFromClient& client, NonnullOwnPtr<Core::File>&& output_stream, i32 request_id)
: m_client(client)
, m_id(s_next_id++)
, m_id(request_id)
, m_output_stream(move(output_stream))
{
}

View File

@ -43,7 +43,7 @@ public:
Core::File const& output_stream() const { return *m_output_stream; }
protected:
explicit Request(ConnectionFromClient&, NonnullOwnPtr<Core::File>&&);
explicit Request(ConnectionFromClient&, NonnullOwnPtr<Core::File>&&, i32 request_id);
private:
ConnectionFromClient& m_client;

View File

@ -2,6 +2,7 @@
endpoint RequestClient
{
request_started(i32 request_id, IPC::File fd) =|
request_progress(i32 request_id, Optional<u64> total_size, u64 downloaded_size) =|
request_finished(i32 request_id, bool success, u64 total_size) =|
headers_became_available(i32 request_id, HashMap<ByteString,ByteString,CaseInsensitiveStringTraits> response_headers, Optional<u32> status_code) =|

View File

@ -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<ByteString,ByteString> request_headers, ByteBuffer request_body, Core::ProxyData proxy_data) => (i32 request_id, Optional<IPC::File> response_fd)
start_request(i32 request_id, ByteString method, URL url, HashMap<ByteString,ByteString> 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)