diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2021-09-28 00:06:52 +0330 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-09-28 22:32:31 +0200 |
commit | 3ec39fc62e5f7a5dd3ce5251777b909220f6cec3 (patch) | |
tree | e37a48e5bc92fb45978b795168f351de117767fc | |
parent | 6b2e4f896be8a096fbd18f1c65c1266456de8808 (diff) | |
download | serenity-3ec39fc62e5f7a5dd3ce5251777b909220f6cec3.zip |
RequestServer+LibProtocol: Add an 'EnsureConnection' IPC endpoint
This will allow LibWeb (and other components) to request a connection to
be premade and cached, to make subsequent loads faster.
6 files changed, 54 insertions, 0 deletions
diff --git a/Userland/Libraries/LibProtocol/RequestClient.cpp b/Userland/Libraries/LibProtocol/RequestClient.cpp index 00a3f57c58..1449468334 100644 --- a/Userland/Libraries/LibProtocol/RequestClient.cpp +++ b/Userland/Libraries/LibProtocol/RequestClient.cpp @@ -15,6 +15,11 @@ RequestClient::RequestClient() { } +void RequestClient::ensure_connection(URL const& url, ::RequestServer::CacheLevel cache_level) +{ + async_ensure_connection(url, cache_level); +} + template<typename RequestHashMapTraits> RefPtr<Request> RequestClient::start_request(String const& method, URL const& url, HashMap<String, String, RequestHashMapTraits> const& request_headers, ReadonlyBytes request_body) { diff --git a/Userland/Libraries/LibProtocol/RequestClient.h b/Userland/Libraries/LibProtocol/RequestClient.h index 7ad2a2fe24..82248e9e3a 100644 --- a/Userland/Libraries/LibProtocol/RequestClient.h +++ b/Userland/Libraries/LibProtocol/RequestClient.h @@ -24,6 +24,8 @@ public: template<typename RequestHashMapTraits = Traits<String>> RefPtr<Request> start_request(String const& method, URL const&, HashMap<String, String, RequestHashMapTraits> const& request_headers = {}, ReadonlyBytes request_body = {}); + void ensure_connection(URL const&, ::RequestServer::CacheLevel); + bool stop_request(Badge<Request>, Request&); bool set_certificate(Badge<Request>, Request&, String, String); diff --git a/Userland/Services/RequestServer/ClientConnection.cpp b/Userland/Services/RequestServer/ClientConnection.cpp index fc9f61ce77..9061ffd16c 100644 --- a/Userland/Services/RequestServer/ClientConnection.cpp +++ b/Userland/Services/RequestServer/ClientConnection.cpp @@ -9,6 +9,7 @@ #include <RequestServer/Protocol.h> #include <RequestServer/Request.h> #include <RequestServer/RequestClientEndpoint.h> +#include <netdb.h> namespace RequestServer { @@ -110,4 +111,37 @@ Messages::RequestServer::SetCertificateResponse ClientConnection::set_certificat return success; } +void ClientConnection::ensure_connection(URL const& url, ::RequestServer::CacheLevel const& cache_level) +{ + if (!url.is_valid()) { + dbgln("EnsureConnection: Invalid URL requested: '{}'", url); + return; + } + + if (cache_level == CacheLevel::ResolveOnly) { + return Core::deferred_invoke([host = url.host()] { + dbgln("EnsureConnection: DNS-preload for {}", host); + (void)gethostbyname(host.characters()); + }); + } + + struct { + URL const& m_url; + void start(NonnullRefPtr<Core::Socket> socket) { socket->connect(m_url.host(), m_url.port_or_default()); } + } job { url }; + + dbgln("EnsureConnection: Pre-connect to {}", url); + auto do_preconnect = [&](auto& cache) { + auto& connection = ConnectionCache::get_or_create_connection(cache, url, job); + connection.removal_timer->start(); + }; + + if (url.scheme() == "http"sv) + do_preconnect(ConnectionCache::g_tcp_connection_cache); + else if (url.scheme() == "https"sv) + do_preconnect(ConnectionCache::g_tls_connection_cache); + else + dbgln("EnsureConnection: Invalid URL scheme: '{}'", url.scheme()); +} + } diff --git a/Userland/Services/RequestServer/ClientConnection.h b/Userland/Services/RequestServer/ClientConnection.h index b01c207672..2822bd7227 100644 --- a/Userland/Services/RequestServer/ClientConnection.h +++ b/Userland/Services/RequestServer/ClientConnection.h @@ -34,6 +34,7 @@ private: virtual Messages::RequestServer::StartRequestResponse start_request(String const&, URL const&, IPC::Dictionary const&, ByteBuffer const&) override; virtual Messages::RequestServer::StopRequestResponse stop_request(i32) override; virtual Messages::RequestServer::SetCertificateResponse set_certificate(i32, String const&, String const&) override; + virtual void ensure_connection(URL const& url, ::RequestServer::CacheLevel const& cache_level) override; HashMap<i32, OwnPtr<Request>> m_requests; }; diff --git a/Userland/Services/RequestServer/ConnectionCache.h b/Userland/Services/RequestServer/ConnectionCache.h index d9bbc0975c..2875709d32 100644 --- a/Userland/Services/RequestServer/ConnectionCache.h +++ b/Userland/Services/RequestServer/ConnectionCache.h @@ -13,6 +13,15 @@ #include <LibCore/Timer.h> #include <LibTLS/TLSv12.h> +namespace RequestServer { + +enum class CacheLevel { + ResolveOnly, + CreateConnection, +}; + +} + namespace RequestServer::ConnectionCache { template<typename Socket> diff --git a/Userland/Services/RequestServer/RequestServer.ipc b/Userland/Services/RequestServer/RequestServer.ipc index cc4219418f..b02be37eb6 100644 --- a/Userland/Services/RequestServer/RequestServer.ipc +++ b/Userland/Services/RequestServer/RequestServer.ipc @@ -1,4 +1,5 @@ #include <AK/URL.h> +#include <RequestServer/ConnectionCache.h> endpoint RequestServer { @@ -8,4 +9,6 @@ endpoint RequestServer start_request(String method, URL url, IPC::Dictionary request_headers, ByteBuffer request_body) => (i32 request_id, Optional<IPC::File> response_fd) stop_request(i32 request_id) => (bool success) set_certificate(i32 request_id, String certificate, String key) => (bool success) + + ensure_connection(URL url, ::RequestServer::CacheLevel cache_level) =| } |