#pragma once

#include <LibCore/AnonymousBuffer.h>
#include <LibCore/Proxy.h>
#include <LibHTTP/Cache/CacheMode.h>
#include <LibHTTP/Cache/DiskCacheSettings.h>
#include <LibHTTP/Cache/Utilities.h>
#include <LibHTTP/Cookie/IncludeCredentials.h>
#include <LibHTTP/Header.h>
#include <LibIPC/TransportHandle.h>
#include <LibURL/URL.h>
#include <RequestServer/CacheLevel.h>
#include <RequestServer/RequestType.h>
#include <AK/Error.h>
#include <AK/MemoryStream.h>
#include <AK/OwnPtr.h>
#include <AK/Platform.h>
#include <AK/Result.h>
#include <AK/Utf8View.h>
#include <LibIPC/Attachment.h>
#include <LibIPC/Connection.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
#include <LibIPC/File.h>
#include <LibIPC/Message.h>
#include <LibIPC/Stub.h>

#if defined(AK_COMPILER_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdefaulted-function-deleted"
#endif

namespace Messages::RequestServer {

enum class MessageID : i32 {
    InitTransport = 1,
    InitTransportResponse = 2,
    ConnectNewClient = 3,
    ConnectNewClientResponse = 4,
    ConnectNewClients = 5,
    ConnectNewClientsResponse = 6,
    SetDiskCacheSettings = 7,
    SetDnsServer = 8,
    SetUseSystemDns = 9,
    IsSupportedProtocol = 10,
    IsSupportedProtocolResponse = 11,
    StartRequest = 12,
    StopRequest = 13,
    StopRequestResponse = 14,
    SetCertificate = 15,
    SetCertificateResponse = 16,
    EnsureConnection = 17,
    RetrievedHttpCookie = 18,
    EstimateCacheSizeAccessedSince = 19,
    RemoveCacheEntriesAccessedSince = 20,
    StoreCacheAssociatedData = 21,
    StoreCacheAssociatedDataResponse = 22,
    RetrieveCacheAssociatedData = 23,
    RetrieveCacheAssociatedDataResponse = 24,
    WebsocketConnect = 25,
    WebsocketSend = 26,
    WebsocketClose = 27,
    WebsocketSetCertificate = 28,
    WebsocketSetCertificateResponse = 29,
};

class InitTransportResponse final : public IPC::Message {
public:
    InitTransportResponse(int peer_pid)
        : m_peer_pid(move(peer_pid))
    {
    }

    InitTransportResponse(InitTransportResponse const&) = default;
    InitTransportResponse(InitTransportResponse&&) = default;
    InitTransportResponse& operator=(InitTransportResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, int>)
    InitTransportResponse(WrappedReturnType&& value)
        : m_peer_pid(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::InitTransportResponse; }
    static i32 static_message_id() { return (int)MessageID::InitTransportResponse; }
    virtual StringView message_name() const override { return "RequestServer::InitTransportResponse"sv; }

    static ErrorOr<NonnullOwnPtr<InitTransportResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto peer_pid = TRY((decoder.decode<int>()));
        return make<InitTransportResponse>(move(peer_pid));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(int peer_pid)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::InitTransportResponse));
        TRY(stream.encode(peer_pid));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_peer_pid);
    }

    int peer_pid() const { return m_peer_pid; }

private:
    int m_peer_pid;
};

class InitTransport final : public IPC::Message {
public:
    typedef class InitTransportResponse ResponseType;

    InitTransport(int peer_pid)
        : m_peer_pid(move(peer_pid))
    {
    }

    InitTransport(InitTransport const&) = default;
    InitTransport(InitTransport&&) = default;
    InitTransport& operator=(InitTransport const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, int>)
    InitTransport(WrappedReturnType&& value)
        : m_peer_pid(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::InitTransport; }
    static i32 static_message_id() { return (int)MessageID::InitTransport; }
    virtual StringView message_name() const override { return "RequestServer::InitTransport"sv; }

    static ErrorOr<NonnullOwnPtr<InitTransport>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto peer_pid = TRY((decoder.decode<int>()));
        return make<InitTransport>(move(peer_pid));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(int peer_pid)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::InitTransport));
        TRY(stream.encode(peer_pid));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_peer_pid);
    }

    int peer_pid() const { return m_peer_pid; }

private:
    int m_peer_pid;
};

class ConnectNewClientResponse final : public IPC::Message {
public:
    ConnectNewClientResponse(IPC::TransportHandle handle)
        : m_handle(move(handle))
    {
    }

    ConnectNewClientResponse(ConnectNewClientResponse const&) = default;
    ConnectNewClientResponse(ConnectNewClientResponse&&) = default;
    ConnectNewClientResponse& operator=(ConnectNewClientResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, IPC::TransportHandle>)
    ConnectNewClientResponse(WrappedReturnType&& value)
        : m_handle(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::ConnectNewClientResponse; }
    static i32 static_message_id() { return (int)MessageID::ConnectNewClientResponse; }
    virtual StringView message_name() const override { return "RequestServer::ConnectNewClientResponse"sv; }

    static ErrorOr<NonnullOwnPtr<ConnectNewClientResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto handle = TRY((decoder.decode<IPC::TransportHandle>()));
        return make<ConnectNewClientResponse>(move(handle));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(IPC::TransportHandle const& handle)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::ConnectNewClientResponse));
        TRY(stream.encode(handle));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_handle);
    }

    IPC::TransportHandle const& handle() const { return m_handle; }
    IPC::TransportHandle take_handle() { return move(m_handle); }

private:
    IPC::TransportHandle m_handle;
};

class ConnectNewClient final : public IPC::Message {
public:
    typedef class ConnectNewClientResponse ResponseType;

    ConnectNewClient() = default;

    ConnectNewClient(ConnectNewClient const&) = default;
    ConnectNewClient(ConnectNewClient&&) = default;
    ConnectNewClient& operator=(ConnectNewClient const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::ConnectNewClient; }
    static i32 static_message_id() { return (int)MessageID::ConnectNewClient; }
    virtual StringView message_name() const override { return "RequestServer::ConnectNewClient"sv; }

    static ErrorOr<NonnullOwnPtr<ConnectNewClient>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        return make<ConnectNewClient>();
    }

    static ErrorOr<IPC::MessageBuffer> static_encode()
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::ConnectNewClient));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode();
    }

private:
};

class ConnectNewClientsResponse final : public IPC::Message {
public:
    ConnectNewClientsResponse(Vector<IPC::TransportHandle> handles)
        : m_handles(move(handles))
    {
    }

    ConnectNewClientsResponse(ConnectNewClientsResponse const&) = default;
    ConnectNewClientsResponse(ConnectNewClientsResponse&&) = default;
    ConnectNewClientsResponse& operator=(ConnectNewClientsResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, Vector<IPC::TransportHandle>>)
    ConnectNewClientsResponse(WrappedReturnType&& value)
        : m_handles(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::ConnectNewClientsResponse; }
    static i32 static_message_id() { return (int)MessageID::ConnectNewClientsResponse; }
    virtual StringView message_name() const override { return "RequestServer::ConnectNewClientsResponse"sv; }

    static ErrorOr<NonnullOwnPtr<ConnectNewClientsResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto handles = TRY((decoder.decode<Vector<IPC::TransportHandle>>()));
        return make<ConnectNewClientsResponse>(move(handles));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(ReadonlySpan<IPC::TransportHandle> handles)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::ConnectNewClientsResponse));
        TRY(stream.encode(handles));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_handles);
    }

    Vector<IPC::TransportHandle> const& handles() const { return m_handles; }
    Vector<IPC::TransportHandle> take_handles() { return move(m_handles); }

private:
    Vector<IPC::TransportHandle> m_handles;
};

class ConnectNewClients final : public IPC::Message {
public:
    typedef class ConnectNewClientsResponse ResponseType;

    ConnectNewClients(size_t count)
        : m_count(move(count))
    {
    }

    ConnectNewClients(ConnectNewClients const&) = default;
    ConnectNewClients(ConnectNewClients&&) = default;
    ConnectNewClients& operator=(ConnectNewClients const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, size_t>)
    ConnectNewClients(WrappedReturnType&& value)
        : m_count(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::ConnectNewClients; }
    static i32 static_message_id() { return (int)MessageID::ConnectNewClients; }
    virtual StringView message_name() const override { return "RequestServer::ConnectNewClients"sv; }

    static ErrorOr<NonnullOwnPtr<ConnectNewClients>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto count = TRY((decoder.decode<size_t>()));
        return make<ConnectNewClients>(move(count));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(size_t count)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::ConnectNewClients));
        TRY(stream.encode(count));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_count);
    }

    size_t count() const { return m_count; }

private:
    size_t m_count;
};

class SetDiskCacheSettings final : public IPC::Message {
public:
    SetDiskCacheSettings(HTTP::DiskCacheSettings disk_cache_settings)
        : m_disk_cache_settings(move(disk_cache_settings))
    {
    }

    SetDiskCacheSettings(SetDiskCacheSettings const&) = default;
    SetDiskCacheSettings(SetDiskCacheSettings&&) = default;
    SetDiskCacheSettings& operator=(SetDiskCacheSettings const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, HTTP::DiskCacheSettings>)
    SetDiskCacheSettings(WrappedReturnType&& value)
        : m_disk_cache_settings(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::SetDiskCacheSettings; }
    static i32 static_message_id() { return (int)MessageID::SetDiskCacheSettings; }
    virtual StringView message_name() const override { return "RequestServer::SetDiskCacheSettings"sv; }

    static ErrorOr<NonnullOwnPtr<SetDiskCacheSettings>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto disk_cache_settings = TRY((decoder.decode<HTTP::DiskCacheSettings>()));
        return make<SetDiskCacheSettings>(move(disk_cache_settings));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(HTTP::DiskCacheSettings const& disk_cache_settings)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::SetDiskCacheSettings));
        TRY(stream.encode(disk_cache_settings));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_disk_cache_settings);
    }

    HTTP::DiskCacheSettings const& disk_cache_settings() const { return m_disk_cache_settings; }
    HTTP::DiskCacheSettings take_disk_cache_settings() { return move(m_disk_cache_settings); }

private:
    HTTP::DiskCacheSettings m_disk_cache_settings;
};

class SetDnsServer final : public IPC::Message {
public:
    SetDnsServer(ByteString host_or_address, u16 port, bool use_tls, bool validate_dnssec_locally)
        : m_host_or_address(move(host_or_address))
        , m_port(move(port))
        , m_use_tls(move(use_tls))
        , m_validate_dnssec_locally(move(validate_dnssec_locally))
    {
    }

    SetDnsServer(SetDnsServer const&) = default;
    SetDnsServer(SetDnsServer&&) = default;
    SetDnsServer& operator=(SetDnsServer const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::SetDnsServer; }
    static i32 static_message_id() { return (int)MessageID::SetDnsServer; }
    virtual StringView message_name() const override { return "RequestServer::SetDnsServer"sv; }

    static ErrorOr<NonnullOwnPtr<SetDnsServer>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto host_or_address = TRY((decoder.decode<ByteString>()));
        auto port = TRY((decoder.decode<u16>()));
        auto use_tls = TRY((decoder.decode<bool>()));
        auto validate_dnssec_locally = TRY((decoder.decode<bool>()));
        return make<SetDnsServer>(move(host_or_address), move(port), move(use_tls), move(validate_dnssec_locally));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(StringView host_or_address, u16 port, bool use_tls, bool validate_dnssec_locally)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::SetDnsServer));
        TRY(stream.encode(host_or_address));
        TRY(stream.encode(port));
        TRY(stream.encode(use_tls));
        TRY(stream.encode(validate_dnssec_locally));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_host_or_address, m_port, m_use_tls, m_validate_dnssec_locally);
    }

    ByteString const& host_or_address() const { return m_host_or_address; }
    ByteString take_host_or_address() { return move(m_host_or_address); }

    u16 port() const { return m_port; }

    bool use_tls() const { return m_use_tls; }

    bool validate_dnssec_locally() const { return m_validate_dnssec_locally; }

private:
    ByteString m_host_or_address;
    u16 m_port;
    bool m_use_tls;
    bool m_validate_dnssec_locally;
};

class SetUseSystemDns final : public IPC::Message {
public:
    SetUseSystemDns() = default;

    SetUseSystemDns(SetUseSystemDns const&) = default;
    SetUseSystemDns(SetUseSystemDns&&) = default;
    SetUseSystemDns& operator=(SetUseSystemDns const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::SetUseSystemDns; }
    static i32 static_message_id() { return (int)MessageID::SetUseSystemDns; }
    virtual StringView message_name() const override { return "RequestServer::SetUseSystemDns"sv; }

    static ErrorOr<NonnullOwnPtr<SetUseSystemDns>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        return make<SetUseSystemDns>();
    }

    static ErrorOr<IPC::MessageBuffer> static_encode()
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::SetUseSystemDns));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode();
    }

private:
};

class IsSupportedProtocolResponse final : public IPC::Message {
public:
    IsSupportedProtocolResponse(bool supported)
        : m_supported(move(supported))
    {
    }

    IsSupportedProtocolResponse(IsSupportedProtocolResponse const&) = default;
    IsSupportedProtocolResponse(IsSupportedProtocolResponse&&) = default;
    IsSupportedProtocolResponse& operator=(IsSupportedProtocolResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, bool>)
    IsSupportedProtocolResponse(WrappedReturnType&& value)
        : m_supported(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::IsSupportedProtocolResponse; }
    static i32 static_message_id() { return (int)MessageID::IsSupportedProtocolResponse; }
    virtual StringView message_name() const override { return "RequestServer::IsSupportedProtocolResponse"sv; }

    static ErrorOr<NonnullOwnPtr<IsSupportedProtocolResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto supported = TRY((decoder.decode<bool>()));
        return make<IsSupportedProtocolResponse>(move(supported));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(bool supported)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::IsSupportedProtocolResponse));
        TRY(stream.encode(supported));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_supported);
    }

    bool supported() const { return m_supported; }

private:
    bool m_supported;
};

class IsSupportedProtocol final : public IPC::Message {
public:
    typedef class IsSupportedProtocolResponse ResponseType;

    IsSupportedProtocol(ByteString protocol)
        : m_protocol(move(protocol))
    {
    }

    IsSupportedProtocol(IsSupportedProtocol const&) = default;
    IsSupportedProtocol(IsSupportedProtocol&&) = default;
    IsSupportedProtocol& operator=(IsSupportedProtocol const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, ByteString>)
    IsSupportedProtocol(WrappedReturnType&& value)
        : m_protocol(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::IsSupportedProtocol; }
    static i32 static_message_id() { return (int)MessageID::IsSupportedProtocol; }
    virtual StringView message_name() const override { return "RequestServer::IsSupportedProtocol"sv; }

    static ErrorOr<NonnullOwnPtr<IsSupportedProtocol>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto protocol = TRY((decoder.decode<ByteString>()));
        return make<IsSupportedProtocol>(move(protocol));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(StringView protocol)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::IsSupportedProtocol));
        TRY(stream.encode(protocol));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_protocol);
    }

    ByteString const& protocol() const { return m_protocol; }
    ByteString take_protocol() { return move(m_protocol); }

private:
    ByteString m_protocol;
};

class StartRequest final : public IPC::Message {
public:
    StartRequest(u64 request_id, ByteString method, URL::URL url, Vector<HTTP::Header> request_headers, ByteBuffer request_body, HTTP::CacheMode cache_mode, HTTP::Cookie::IncludeCredentials include_credentials, Core::ProxyData proxy_data)
        : m_request_id(move(request_id))
        , m_method(move(method))
        , m_url(move(url))
        , m_request_headers(move(request_headers))
        , m_request_body(move(request_body))
        , m_cache_mode(move(cache_mode))
        , m_include_credentials(move(include_credentials))
        , m_proxy_data(move(proxy_data))
    {
    }

    StartRequest(StartRequest const&) = default;
    StartRequest(StartRequest&&) = default;
    StartRequest& operator=(StartRequest const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::StartRequest; }
    static i32 static_message_id() { return (int)MessageID::StartRequest; }
    virtual StringView message_name() const override { return "RequestServer::StartRequest"sv; }

    static ErrorOr<NonnullOwnPtr<StartRequest>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto request_id = TRY((decoder.decode<u64>()));
        auto method = TRY((decoder.decode<ByteString>()));
        auto url = TRY((decoder.decode<URL::URL>()));
        auto request_headers = TRY((decoder.decode<Vector<HTTP::Header>>()));
        auto request_body = TRY((decoder.decode<ByteBuffer>()));
        auto cache_mode = TRY((decoder.decode<HTTP::CacheMode>()));
        auto include_credentials = TRY((decoder.decode<HTTP::Cookie::IncludeCredentials>()));
        auto proxy_data = TRY((decoder.decode<Core::ProxyData>()));
        return make<StartRequest>(move(request_id), move(method), move(url), move(request_headers), move(request_body), move(cache_mode), move(include_credentials), move(proxy_data));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(u64 request_id, StringView method, URL::URL const& url, ReadonlySpan<HTTP::Header> request_headers, ReadonlyBytes request_body, HTTP::CacheMode const& cache_mode, HTTP::Cookie::IncludeCredentials const& include_credentials, Core::ProxyData const& proxy_data)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::StartRequest));
        TRY(stream.encode(request_id));
        TRY(stream.encode(method));
        TRY(stream.encode(url));
        TRY(stream.encode(request_headers));
        TRY(stream.encode(request_body));
        TRY(stream.encode(cache_mode));
        TRY(stream.encode(include_credentials));
        TRY(stream.encode(proxy_data));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_request_id, m_method, m_url, m_request_headers, m_request_body, m_cache_mode, m_include_credentials, m_proxy_data);
    }

    u64 request_id() const { return m_request_id; }

    ByteString const& method() const { return m_method; }
    ByteString take_method() { return move(m_method); }

    URL::URL const& url() const { return m_url; }
    URL::URL take_url() { return move(m_url); }

    Vector<HTTP::Header> const& request_headers() const { return m_request_headers; }
    Vector<HTTP::Header> take_request_headers() { return move(m_request_headers); }

    ByteBuffer const& request_body() const { return m_request_body; }
    ByteBuffer take_request_body() { return move(m_request_body); }

    HTTP::CacheMode const& cache_mode() const { return m_cache_mode; }
    HTTP::CacheMode take_cache_mode() { return move(m_cache_mode); }

    HTTP::Cookie::IncludeCredentials const& include_credentials() const { return m_include_credentials; }
    HTTP::Cookie::IncludeCredentials take_include_credentials() { return move(m_include_credentials); }

    Core::ProxyData const& proxy_data() const { return m_proxy_data; }
    Core::ProxyData take_proxy_data() { return move(m_proxy_data); }

private:
    u64 m_request_id;
    ByteString m_method;
    URL::URL m_url;
    Vector<HTTP::Header> m_request_headers;
    ByteBuffer m_request_body;
    HTTP::CacheMode m_cache_mode;
    HTTP::Cookie::IncludeCredentials m_include_credentials;
    Core::ProxyData m_proxy_data;
};

class StopRequestResponse final : public IPC::Message {
public:
    StopRequestResponse(bool success)
        : m_success(move(success))
    {
    }

    StopRequestResponse(StopRequestResponse const&) = default;
    StopRequestResponse(StopRequestResponse&&) = default;
    StopRequestResponse& operator=(StopRequestResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, bool>)
    StopRequestResponse(WrappedReturnType&& value)
        : m_success(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::StopRequestResponse; }
    static i32 static_message_id() { return (int)MessageID::StopRequestResponse; }
    virtual StringView message_name() const override { return "RequestServer::StopRequestResponse"sv; }

    static ErrorOr<NonnullOwnPtr<StopRequestResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto success = TRY((decoder.decode<bool>()));
        return make<StopRequestResponse>(move(success));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(bool success)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::StopRequestResponse));
        TRY(stream.encode(success));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_success);
    }

    bool success() const { return m_success; }

private:
    bool m_success;
};

class StopRequest final : public IPC::Message {
public:
    typedef class StopRequestResponse ResponseType;

    StopRequest(u64 request_id)
        : m_request_id(move(request_id))
    {
    }

    StopRequest(StopRequest const&) = default;
    StopRequest(StopRequest&&) = default;
    StopRequest& operator=(StopRequest const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, u64>)
    StopRequest(WrappedReturnType&& value)
        : m_request_id(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::StopRequest; }
    static i32 static_message_id() { return (int)MessageID::StopRequest; }
    virtual StringView message_name() const override { return "RequestServer::StopRequest"sv; }

    static ErrorOr<NonnullOwnPtr<StopRequest>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto request_id = TRY((decoder.decode<u64>()));
        return make<StopRequest>(move(request_id));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(u64 request_id)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::StopRequest));
        TRY(stream.encode(request_id));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_request_id);
    }

    u64 request_id() const { return m_request_id; }

private:
    u64 m_request_id;
};

class SetCertificateResponse final : public IPC::Message {
public:
    SetCertificateResponse(bool success)
        : m_success(move(success))
    {
    }

    SetCertificateResponse(SetCertificateResponse const&) = default;
    SetCertificateResponse(SetCertificateResponse&&) = default;
    SetCertificateResponse& operator=(SetCertificateResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, bool>)
    SetCertificateResponse(WrappedReturnType&& value)
        : m_success(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::SetCertificateResponse; }
    static i32 static_message_id() { return (int)MessageID::SetCertificateResponse; }
    virtual StringView message_name() const override { return "RequestServer::SetCertificateResponse"sv; }

    static ErrorOr<NonnullOwnPtr<SetCertificateResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto success = TRY((decoder.decode<bool>()));
        return make<SetCertificateResponse>(move(success));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(bool success)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::SetCertificateResponse));
        TRY(stream.encode(success));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_success);
    }

    bool success() const { return m_success; }

private:
    bool m_success;
};

class SetCertificate final : public IPC::Message {
public:
    typedef class SetCertificateResponse ResponseType;

    SetCertificate(u64 request_id, ByteString certificate, ByteString key)
        : m_request_id(move(request_id))
        , m_certificate(move(certificate))
        , m_key(move(key))
    {
    }

    SetCertificate(SetCertificate const&) = default;
    SetCertificate(SetCertificate&&) = default;
    SetCertificate& operator=(SetCertificate const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::SetCertificate; }
    static i32 static_message_id() { return (int)MessageID::SetCertificate; }
    virtual StringView message_name() const override { return "RequestServer::SetCertificate"sv; }

    static ErrorOr<NonnullOwnPtr<SetCertificate>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto request_id = TRY((decoder.decode<u64>()));
        auto certificate = TRY((decoder.decode<ByteString>()));
        auto key = TRY((decoder.decode<ByteString>()));
        return make<SetCertificate>(move(request_id), move(certificate), move(key));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(u64 request_id, StringView certificate, StringView key)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::SetCertificate));
        TRY(stream.encode(request_id));
        TRY(stream.encode(certificate));
        TRY(stream.encode(key));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_request_id, m_certificate, m_key);
    }

    u64 request_id() const { return m_request_id; }

    ByteString const& certificate() const { return m_certificate; }
    ByteString take_certificate() { return move(m_certificate); }

    ByteString const& key() const { return m_key; }
    ByteString take_key() { return move(m_key); }

private:
    u64 m_request_id;
    ByteString m_certificate;
    ByteString m_key;
};

class EnsureConnection final : public IPC::Message {
public:
    EnsureConnection(u64 request_id, URL::URL url, ::RequestServer::CacheLevel cache_level)
        : m_request_id(move(request_id))
        , m_url(move(url))
        , m_cache_level(move(cache_level))
    {
    }

    EnsureConnection(EnsureConnection const&) = default;
    EnsureConnection(EnsureConnection&&) = default;
    EnsureConnection& operator=(EnsureConnection const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::EnsureConnection; }
    static i32 static_message_id() { return (int)MessageID::EnsureConnection; }
    virtual StringView message_name() const override { return "RequestServer::EnsureConnection"sv; }

    static ErrorOr<NonnullOwnPtr<EnsureConnection>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto request_id = TRY((decoder.decode<u64>()));
        auto url = TRY((decoder.decode<URL::URL>()));
        auto cache_level = TRY((decoder.decode<::RequestServer::CacheLevel>()));
        return make<EnsureConnection>(move(request_id), move(url), move(cache_level));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(u64 request_id, URL::URL const& url, ::RequestServer::CacheLevel const& cache_level)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::EnsureConnection));
        TRY(stream.encode(request_id));
        TRY(stream.encode(url));
        TRY(stream.encode(cache_level));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_request_id, m_url, m_cache_level);
    }

    u64 request_id() const { return m_request_id; }

    URL::URL const& url() const { return m_url; }
    URL::URL take_url() { return move(m_url); }

    ::RequestServer::CacheLevel const& cache_level() const { return m_cache_level; }
    ::RequestServer::CacheLevel take_cache_level() { return move(m_cache_level); }

private:
    u64 m_request_id;
    URL::URL m_url;
    ::RequestServer::CacheLevel m_cache_level;
};

class RetrievedHttpCookie final : public IPC::Message {
public:
    RetrievedHttpCookie(int client_id, u64 request_id, ::RequestServer::RequestType request_type, String cookie)
        : m_client_id(move(client_id))
        , m_request_id(move(request_id))
        , m_request_type(move(request_type))
        , m_cookie(move(cookie))
    {
    }

    RetrievedHttpCookie(RetrievedHttpCookie const&) = default;
    RetrievedHttpCookie(RetrievedHttpCookie&&) = default;
    RetrievedHttpCookie& operator=(RetrievedHttpCookie const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::RetrievedHttpCookie; }
    static i32 static_message_id() { return (int)MessageID::RetrievedHttpCookie; }
    virtual StringView message_name() const override { return "RequestServer::RetrievedHttpCookie"sv; }

    static ErrorOr<NonnullOwnPtr<RetrievedHttpCookie>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto client_id = TRY((decoder.decode<int>()));
        auto request_id = TRY((decoder.decode<u64>()));
        auto request_type = TRY((decoder.decode<::RequestServer::RequestType>()));
        auto cookie = TRY((decoder.decode<String>()));
        return make<RetrievedHttpCookie>(move(client_id), move(request_id), move(request_type), move(cookie));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(int client_id, u64 request_id, ::RequestServer::RequestType const& request_type, StringView cookie)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::RetrievedHttpCookie));
        TRY(stream.encode(client_id));
        TRY(stream.encode(request_id));
        TRY(stream.encode(request_type));
        TRY(stream.encode(cookie));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_client_id, m_request_id, m_request_type, m_cookie);
    }

    int client_id() const { return m_client_id; }

    u64 request_id() const { return m_request_id; }

    ::RequestServer::RequestType const& request_type() const { return m_request_type; }
    ::RequestServer::RequestType take_request_type() { return move(m_request_type); }

    String const& cookie() const { return m_cookie; }
    String take_cookie() { return move(m_cookie); }

private:
    int m_client_id;
    u64 m_request_id;
    ::RequestServer::RequestType m_request_type;
    String m_cookie;
};

class EstimateCacheSizeAccessedSince final : public IPC::Message {
public:
    EstimateCacheSizeAccessedSince(u64 cache_size_estimation_id, UnixDateTime since)
        : m_cache_size_estimation_id(move(cache_size_estimation_id))
        , m_since(move(since))
    {
    }

    EstimateCacheSizeAccessedSince(EstimateCacheSizeAccessedSince const&) = default;
    EstimateCacheSizeAccessedSince(EstimateCacheSizeAccessedSince&&) = default;
    EstimateCacheSizeAccessedSince& operator=(EstimateCacheSizeAccessedSince const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::EstimateCacheSizeAccessedSince; }
    static i32 static_message_id() { return (int)MessageID::EstimateCacheSizeAccessedSince; }
    virtual StringView message_name() const override { return "RequestServer::EstimateCacheSizeAccessedSince"sv; }

    static ErrorOr<NonnullOwnPtr<EstimateCacheSizeAccessedSince>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto cache_size_estimation_id = TRY((decoder.decode<u64>()));
        auto since = TRY((decoder.decode<UnixDateTime>()));
        return make<EstimateCacheSizeAccessedSince>(move(cache_size_estimation_id), move(since));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(u64 cache_size_estimation_id, UnixDateTime const& since)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::EstimateCacheSizeAccessedSince));
        TRY(stream.encode(cache_size_estimation_id));
        TRY(stream.encode(since));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_cache_size_estimation_id, m_since);
    }

    u64 cache_size_estimation_id() const { return m_cache_size_estimation_id; }

    UnixDateTime const& since() const { return m_since; }
    UnixDateTime take_since() { return move(m_since); }

private:
    u64 m_cache_size_estimation_id;
    UnixDateTime m_since;
};

class RemoveCacheEntriesAccessedSince final : public IPC::Message {
public:
    RemoveCacheEntriesAccessedSince(UnixDateTime since)
        : m_since(move(since))
    {
    }

    RemoveCacheEntriesAccessedSince(RemoveCacheEntriesAccessedSince const&) = default;
    RemoveCacheEntriesAccessedSince(RemoveCacheEntriesAccessedSince&&) = default;
    RemoveCacheEntriesAccessedSince& operator=(RemoveCacheEntriesAccessedSince const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, UnixDateTime>)
    RemoveCacheEntriesAccessedSince(WrappedReturnType&& value)
        : m_since(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::RemoveCacheEntriesAccessedSince; }
    static i32 static_message_id() { return (int)MessageID::RemoveCacheEntriesAccessedSince; }
    virtual StringView message_name() const override { return "RequestServer::RemoveCacheEntriesAccessedSince"sv; }

    static ErrorOr<NonnullOwnPtr<RemoveCacheEntriesAccessedSince>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto since = TRY((decoder.decode<UnixDateTime>()));
        return make<RemoveCacheEntriesAccessedSince>(move(since));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(UnixDateTime const& since)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::RemoveCacheEntriesAccessedSince));
        TRY(stream.encode(since));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_since);
    }

    UnixDateTime const& since() const { return m_since; }
    UnixDateTime take_since() { return move(m_since); }

private:
    UnixDateTime m_since;
};

class StoreCacheAssociatedDataResponse final : public IPC::Message {
public:
    StoreCacheAssociatedDataResponse(bool stored)
        : m_stored(move(stored))
    {
    }

    StoreCacheAssociatedDataResponse(StoreCacheAssociatedDataResponse const&) = default;
    StoreCacheAssociatedDataResponse(StoreCacheAssociatedDataResponse&&) = default;
    StoreCacheAssociatedDataResponse& operator=(StoreCacheAssociatedDataResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, bool>)
    StoreCacheAssociatedDataResponse(WrappedReturnType&& value)
        : m_stored(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::StoreCacheAssociatedDataResponse; }
    static i32 static_message_id() { return (int)MessageID::StoreCacheAssociatedDataResponse; }
    virtual StringView message_name() const override { return "RequestServer::StoreCacheAssociatedDataResponse"sv; }

    static ErrorOr<NonnullOwnPtr<StoreCacheAssociatedDataResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto stored = TRY((decoder.decode<bool>()));
        return make<StoreCacheAssociatedDataResponse>(move(stored));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(bool stored)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::StoreCacheAssociatedDataResponse));
        TRY(stream.encode(stored));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_stored);
    }

    bool stored() const { return m_stored; }

private:
    bool m_stored;
};

class StoreCacheAssociatedData final : public IPC::Message {
public:
    typedef class StoreCacheAssociatedDataResponse ResponseType;

    StoreCacheAssociatedData(URL::URL url, ByteString method, Vector<HTTP::Header> request_headers, Optional<u64> vary_key, HTTP::CacheEntryAssociatedData associated_data, Core::AnonymousBuffer data)
        : m_url(move(url))
        , m_method(move(method))
        , m_request_headers(move(request_headers))
        , m_vary_key(move(vary_key))
        , m_associated_data(move(associated_data))
        , m_data(move(data))
    {
    }

    StoreCacheAssociatedData(StoreCacheAssociatedData const&) = default;
    StoreCacheAssociatedData(StoreCacheAssociatedData&&) = default;
    StoreCacheAssociatedData& operator=(StoreCacheAssociatedData const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::StoreCacheAssociatedData; }
    static i32 static_message_id() { return (int)MessageID::StoreCacheAssociatedData; }
    virtual StringView message_name() const override { return "RequestServer::StoreCacheAssociatedData"sv; }

    static ErrorOr<NonnullOwnPtr<StoreCacheAssociatedData>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto url = TRY((decoder.decode<URL::URL>()));
        auto method = TRY((decoder.decode<ByteString>()));
        auto request_headers = TRY((decoder.decode<Vector<HTTP::Header>>()));
        auto vary_key = TRY((decoder.decode<Optional<u64>>()));
        auto associated_data = TRY((decoder.decode<HTTP::CacheEntryAssociatedData>()));
        auto data = TRY((decoder.decode<Core::AnonymousBuffer>()));
        return make<StoreCacheAssociatedData>(move(url), move(method), move(request_headers), move(vary_key), move(associated_data), move(data));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(URL::URL const& url, StringView method, ReadonlySpan<HTTP::Header> request_headers, Optional<u64> const& vary_key, HTTP::CacheEntryAssociatedData const& associated_data, Core::AnonymousBuffer const& data)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::StoreCacheAssociatedData));
        TRY(stream.encode(url));
        TRY(stream.encode(method));
        TRY(stream.encode(request_headers));
        TRY(stream.encode(vary_key));
        TRY(stream.encode(associated_data));
        TRY(stream.encode(data));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_url, m_method, m_request_headers, m_vary_key, m_associated_data, m_data);
    }

    URL::URL const& url() const { return m_url; }
    URL::URL take_url() { return move(m_url); }

    ByteString const& method() const { return m_method; }
    ByteString take_method() { return move(m_method); }

    Vector<HTTP::Header> const& request_headers() const { return m_request_headers; }
    Vector<HTTP::Header> take_request_headers() { return move(m_request_headers); }

    Optional<u64> const& vary_key() const { return m_vary_key; }
    Optional<u64> take_vary_key() { return move(m_vary_key); }

    HTTP::CacheEntryAssociatedData const& associated_data() const { return m_associated_data; }
    HTTP::CacheEntryAssociatedData take_associated_data() { return move(m_associated_data); }

    Core::AnonymousBuffer const& data() const { return m_data; }
    Core::AnonymousBuffer take_data() { return move(m_data); }

private:
    URL::URL m_url;
    ByteString m_method;
    Vector<HTTP::Header> m_request_headers;
    Optional<u64> m_vary_key;
    HTTP::CacheEntryAssociatedData m_associated_data;
    Core::AnonymousBuffer m_data;
};

class RetrieveCacheAssociatedDataResponse final : public IPC::Message {
public:
    RetrieveCacheAssociatedDataResponse(Optional<Core::AnonymousBuffer> data)
        : m_data(move(data))
    {
    }

    RetrieveCacheAssociatedDataResponse(RetrieveCacheAssociatedDataResponse const&) = default;
    RetrieveCacheAssociatedDataResponse(RetrieveCacheAssociatedDataResponse&&) = default;
    RetrieveCacheAssociatedDataResponse& operator=(RetrieveCacheAssociatedDataResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, Optional<Core::AnonymousBuffer>>)
    RetrieveCacheAssociatedDataResponse(WrappedReturnType&& value)
        : m_data(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::RetrieveCacheAssociatedDataResponse; }
    static i32 static_message_id() { return (int)MessageID::RetrieveCacheAssociatedDataResponse; }
    virtual StringView message_name() const override { return "RequestServer::RetrieveCacheAssociatedDataResponse"sv; }

    static ErrorOr<NonnullOwnPtr<RetrieveCacheAssociatedDataResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto data = TRY((decoder.decode<Optional<Core::AnonymousBuffer>>()));
        return make<RetrieveCacheAssociatedDataResponse>(move(data));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(Optional<Core::AnonymousBuffer> const& data)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::RetrieveCacheAssociatedDataResponse));
        TRY(stream.encode(data));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_data);
    }

    Optional<Core::AnonymousBuffer> const& data() const { return m_data; }
    Optional<Core::AnonymousBuffer> take_data() { return move(m_data); }

private:
    Optional<Core::AnonymousBuffer> m_data;
};

class RetrieveCacheAssociatedData final : public IPC::Message {
public:
    typedef class RetrieveCacheAssociatedDataResponse ResponseType;

    RetrieveCacheAssociatedData(URL::URL url, ByteString method, Vector<HTTP::Header> request_headers, Optional<u64> vary_key, HTTP::CacheEntryAssociatedData associated_data)
        : m_url(move(url))
        , m_method(move(method))
        , m_request_headers(move(request_headers))
        , m_vary_key(move(vary_key))
        , m_associated_data(move(associated_data))
    {
    }

    RetrieveCacheAssociatedData(RetrieveCacheAssociatedData const&) = default;
    RetrieveCacheAssociatedData(RetrieveCacheAssociatedData&&) = default;
    RetrieveCacheAssociatedData& operator=(RetrieveCacheAssociatedData const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::RetrieveCacheAssociatedData; }
    static i32 static_message_id() { return (int)MessageID::RetrieveCacheAssociatedData; }
    virtual StringView message_name() const override { return "RequestServer::RetrieveCacheAssociatedData"sv; }

    static ErrorOr<NonnullOwnPtr<RetrieveCacheAssociatedData>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto url = TRY((decoder.decode<URL::URL>()));
        auto method = TRY((decoder.decode<ByteString>()));
        auto request_headers = TRY((decoder.decode<Vector<HTTP::Header>>()));
        auto vary_key = TRY((decoder.decode<Optional<u64>>()));
        auto associated_data = TRY((decoder.decode<HTTP::CacheEntryAssociatedData>()));
        return make<RetrieveCacheAssociatedData>(move(url), move(method), move(request_headers), move(vary_key), move(associated_data));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(URL::URL const& url, StringView method, ReadonlySpan<HTTP::Header> request_headers, Optional<u64> const& vary_key, HTTP::CacheEntryAssociatedData const& associated_data)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::RetrieveCacheAssociatedData));
        TRY(stream.encode(url));
        TRY(stream.encode(method));
        TRY(stream.encode(request_headers));
        TRY(stream.encode(vary_key));
        TRY(stream.encode(associated_data));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_url, m_method, m_request_headers, m_vary_key, m_associated_data);
    }

    URL::URL const& url() const { return m_url; }
    URL::URL take_url() { return move(m_url); }

    ByteString const& method() const { return m_method; }
    ByteString take_method() { return move(m_method); }

    Vector<HTTP::Header> const& request_headers() const { return m_request_headers; }
    Vector<HTTP::Header> take_request_headers() { return move(m_request_headers); }

    Optional<u64> const& vary_key() const { return m_vary_key; }
    Optional<u64> take_vary_key() { return move(m_vary_key); }

    HTTP::CacheEntryAssociatedData const& associated_data() const { return m_associated_data; }
    HTTP::CacheEntryAssociatedData take_associated_data() { return move(m_associated_data); }

private:
    URL::URL m_url;
    ByteString m_method;
    Vector<HTTP::Header> m_request_headers;
    Optional<u64> m_vary_key;
    HTTP::CacheEntryAssociatedData m_associated_data;
};

class WebsocketConnect final : public IPC::Message {
public:
    WebsocketConnect(u64 websocket_id, URL::URL url, ByteString origin, Vector<ByteString> protocols, Vector<ByteString> extensions, Vector<HTTP::Header> additional_request_headers)
        : m_websocket_id(move(websocket_id))
        , m_url(move(url))
        , m_origin(move(origin))
        , m_protocols(move(protocols))
        , m_extensions(move(extensions))
        , m_additional_request_headers(move(additional_request_headers))
    {
    }

    WebsocketConnect(WebsocketConnect const&) = default;
    WebsocketConnect(WebsocketConnect&&) = default;
    WebsocketConnect& operator=(WebsocketConnect const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::WebsocketConnect; }
    static i32 static_message_id() { return (int)MessageID::WebsocketConnect; }
    virtual StringView message_name() const override { return "RequestServer::WebsocketConnect"sv; }

    static ErrorOr<NonnullOwnPtr<WebsocketConnect>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto websocket_id = TRY((decoder.decode<u64>()));
        auto url = TRY((decoder.decode<URL::URL>()));
        auto origin = TRY((decoder.decode<ByteString>()));
        auto protocols = TRY((decoder.decode<Vector<ByteString>>()));
        auto extensions = TRY((decoder.decode<Vector<ByteString>>()));
        auto additional_request_headers = TRY((decoder.decode<Vector<HTTP::Header>>()));
        return make<WebsocketConnect>(move(websocket_id), move(url), move(origin), move(protocols), move(extensions), move(additional_request_headers));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(u64 websocket_id, URL::URL const& url, StringView origin, ReadonlySpan<ByteString> protocols, ReadonlySpan<ByteString> extensions, ReadonlySpan<HTTP::Header> additional_request_headers)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::WebsocketConnect));
        TRY(stream.encode(websocket_id));
        TRY(stream.encode(url));
        TRY(stream.encode(origin));
        TRY(stream.encode(protocols));
        TRY(stream.encode(extensions));
        TRY(stream.encode(additional_request_headers));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_websocket_id, m_url, m_origin, m_protocols, m_extensions, m_additional_request_headers);
    }

    u64 websocket_id() const { return m_websocket_id; }

    URL::URL const& url() const { return m_url; }
    URL::URL take_url() { return move(m_url); }

    ByteString const& origin() const { return m_origin; }
    ByteString take_origin() { return move(m_origin); }

    Vector<ByteString> const& protocols() const { return m_protocols; }
    Vector<ByteString> take_protocols() { return move(m_protocols); }

    Vector<ByteString> const& extensions() const { return m_extensions; }
    Vector<ByteString> take_extensions() { return move(m_extensions); }

    Vector<HTTP::Header> const& additional_request_headers() const { return m_additional_request_headers; }
    Vector<HTTP::Header> take_additional_request_headers() { return move(m_additional_request_headers); }

private:
    u64 m_websocket_id;
    URL::URL m_url;
    ByteString m_origin;
    Vector<ByteString> m_protocols;
    Vector<ByteString> m_extensions;
    Vector<HTTP::Header> m_additional_request_headers;
};

class WebsocketSend final : public IPC::Message {
public:
    WebsocketSend(u64 websocket_id, bool is_text, ByteBuffer data)
        : m_websocket_id(move(websocket_id))
        , m_is_text(move(is_text))
        , m_data(move(data))
    {
    }

    WebsocketSend(WebsocketSend const&) = default;
    WebsocketSend(WebsocketSend&&) = default;
    WebsocketSend& operator=(WebsocketSend const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::WebsocketSend; }
    static i32 static_message_id() { return (int)MessageID::WebsocketSend; }
    virtual StringView message_name() const override { return "RequestServer::WebsocketSend"sv; }

    static ErrorOr<NonnullOwnPtr<WebsocketSend>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto websocket_id = TRY((decoder.decode<u64>()));
        auto is_text = TRY((decoder.decode<bool>()));
        auto data = TRY((decoder.decode<ByteBuffer>()));
        return make<WebsocketSend>(move(websocket_id), move(is_text), move(data));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(u64 websocket_id, bool is_text, ReadonlyBytes data)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::WebsocketSend));
        TRY(stream.encode(websocket_id));
        TRY(stream.encode(is_text));
        TRY(stream.encode(data));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_websocket_id, m_is_text, m_data);
    }

    u64 websocket_id() const { return m_websocket_id; }

    bool is_text() const { return m_is_text; }

    ByteBuffer const& data() const { return m_data; }
    ByteBuffer take_data() { return move(m_data); }

private:
    u64 m_websocket_id;
    bool m_is_text;
    ByteBuffer m_data;
};

class WebsocketClose final : public IPC::Message {
public:
    WebsocketClose(u64 websocket_id, u16 code, ByteString reason)
        : m_websocket_id(move(websocket_id))
        , m_code(move(code))
        , m_reason(move(reason))
    {
    }

    WebsocketClose(WebsocketClose const&) = default;
    WebsocketClose(WebsocketClose&&) = default;
    WebsocketClose& operator=(WebsocketClose const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::WebsocketClose; }
    static i32 static_message_id() { return (int)MessageID::WebsocketClose; }
    virtual StringView message_name() const override { return "RequestServer::WebsocketClose"sv; }

    static ErrorOr<NonnullOwnPtr<WebsocketClose>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto websocket_id = TRY((decoder.decode<u64>()));
        auto code = TRY((decoder.decode<u16>()));
        auto reason = TRY((decoder.decode<ByteString>()));
        return make<WebsocketClose>(move(websocket_id), move(code), move(reason));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(u64 websocket_id, u16 code, StringView reason)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::WebsocketClose));
        TRY(stream.encode(websocket_id));
        TRY(stream.encode(code));
        TRY(stream.encode(reason));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_websocket_id, m_code, m_reason);
    }

    u64 websocket_id() const { return m_websocket_id; }

    u16 code() const { return m_code; }

    ByteString const& reason() const { return m_reason; }
    ByteString take_reason() { return move(m_reason); }

private:
    u64 m_websocket_id;
    u16 m_code;
    ByteString m_reason;
};

class WebsocketSetCertificateResponse final : public IPC::Message {
public:
    WebsocketSetCertificateResponse(bool success)
        : m_success(move(success))
    {
    }

    WebsocketSetCertificateResponse(WebsocketSetCertificateResponse const&) = default;
    WebsocketSetCertificateResponse(WebsocketSetCertificateResponse&&) = default;
    WebsocketSetCertificateResponse& operator=(WebsocketSetCertificateResponse const&) = default;

    template<typename WrappedReturnType>
    requires(!SameAs<WrappedReturnType, bool>)
    WebsocketSetCertificateResponse(WrappedReturnType&& value)
        : m_success(forward<WrappedReturnType>(value))
    {
    }

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::WebsocketSetCertificateResponse; }
    static i32 static_message_id() { return (int)MessageID::WebsocketSetCertificateResponse; }
    virtual StringView message_name() const override { return "RequestServer::WebsocketSetCertificateResponse"sv; }

    static ErrorOr<NonnullOwnPtr<WebsocketSetCertificateResponse>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto success = TRY((decoder.decode<bool>()));
        return make<WebsocketSetCertificateResponse>(move(success));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(bool success)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::WebsocketSetCertificateResponse));
        TRY(stream.encode(success));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_success);
    }

    bool success() const { return m_success; }

private:
    bool m_success;
};

class WebsocketSetCertificate final : public IPC::Message {
public:
    typedef class WebsocketSetCertificateResponse ResponseType;

    WebsocketSetCertificate(u64 request_id, ByteString certificate, ByteString key)
        : m_request_id(move(request_id))
        , m_certificate(move(certificate))
        , m_key(move(key))
    {
    }

    WebsocketSetCertificate(WebsocketSetCertificate const&) = default;
    WebsocketSetCertificate(WebsocketSetCertificate&&) = default;
    WebsocketSetCertificate& operator=(WebsocketSetCertificate const&) = default;

    static constexpr u32 ENDPOINT_MAGIC = 1270977860;

    virtual u32 endpoint_magic() const override { return ENDPOINT_MAGIC; }
    virtual i32 message_id() const override { return (int)MessageID::WebsocketSetCertificate; }
    static i32 static_message_id() { return (int)MessageID::WebsocketSetCertificate; }
    virtual StringView message_name() const override { return "RequestServer::WebsocketSetCertificate"sv; }

    static ErrorOr<NonnullOwnPtr<WebsocketSetCertificate>> decode(Stream& stream, Queue<IPC::Attachment>& attachments)
    {
        IPC::Decoder decoder { stream, attachments };
        auto request_id = TRY((decoder.decode<u64>()));
        auto certificate = TRY((decoder.decode<ByteString>()));
        auto key = TRY((decoder.decode<ByteString>()));
        return make<WebsocketSetCertificate>(move(request_id), move(certificate), move(key));
    }

    static ErrorOr<IPC::MessageBuffer> static_encode(u64 request_id, StringView certificate, StringView key)
    {
        IPC::MessageBuffer buffer;
        IPC::Encoder stream(buffer);
        TRY(stream.encode(ENDPOINT_MAGIC));
        TRY(stream.encode((int)MessageID::WebsocketSetCertificate));
        TRY(stream.encode(request_id));
        TRY(stream.encode(certificate));
        TRY(stream.encode(key));
        return buffer;
    }

    virtual ErrorOr<IPC::MessageBuffer> encode() const override
    {
        return static_encode(m_request_id, m_certificate, m_key);
    }

    u64 request_id() const { return m_request_id; }

    ByteString const& certificate() const { return m_certificate; }
    ByteString take_certificate() { return move(m_certificate); }

    ByteString const& key() const { return m_key; }
    ByteString take_key() { return move(m_key); }

private:
    u64 m_request_id;
    ByteString m_certificate;
    ByteString m_key;
};

} // namespace Messages::RequestServer

template<typename LocalEndpoint, typename PeerEndpoint>
class RequestServerProxy {
public:
    // Used to disambiguate the constructor call.
    struct Tag { };

    RequestServerProxy(IPC::Connection<LocalEndpoint, PeerEndpoint>& connection, Tag)
        : m_connection(connection)
    {
    }

    int init_transport(int peer_pid)
    {
        return m_connection.template send_sync<Messages::RequestServer::InitTransport>(peer_pid)->peer_pid();
    }

    void async_init_transport(int peer_pid)
    {
        auto message_buffer = MUST(Messages::RequestServer::InitTransport::static_encode(peer_pid));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<int> try_init_transport(int peer_pid)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::RequestServer::InitTransport>(peer_pid))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    IPC::TransportHandle connect_new_client()
    {
        return m_connection.template send_sync<Messages::RequestServer::ConnectNewClient>()->take_handle();
    }

    void async_connect_new_client()
    {
        auto message_buffer = MUST(Messages::RequestServer::ConnectNewClient::static_encode());
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<IPC::TransportHandle> try_connect_new_client()
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::RequestServer::ConnectNewClient>())
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    Vector<IPC::TransportHandle> connect_new_clients(size_t count)
    {
        return m_connection.template send_sync<Messages::RequestServer::ConnectNewClients>(count)->take_handles();
    }

    void async_connect_new_clients(size_t count)
    {
        auto message_buffer = MUST(Messages::RequestServer::ConnectNewClients::static_encode(count));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<Vector<IPC::TransportHandle>> try_connect_new_clients(size_t count)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::RequestServer::ConnectNewClients>(count))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    void async_set_disk_cache_settings(HTTP::DiskCacheSettings const& disk_cache_settings)
    {
        auto message_buffer = MUST(Messages::RequestServer::SetDiskCacheSettings::static_encode(move(disk_cache_settings)));
        (void)m_connection.post_message(message_buffer);
    }

    void async_set_dns_server(StringView host_or_address, u16 port, bool use_tls, bool validate_dnssec_locally)
    {
        auto message_buffer = MUST(Messages::RequestServer::SetDnsServer::static_encode(host_or_address, port, use_tls, validate_dnssec_locally));
        (void)m_connection.post_message(message_buffer);
    }

    void async_set_use_system_dns()
    {
        auto message_buffer = MUST(Messages::RequestServer::SetUseSystemDns::static_encode());
        (void)m_connection.post_message(message_buffer);
    }

    bool is_supported_protocol(ByteString protocol)
    {
        return m_connection.template send_sync<Messages::RequestServer::IsSupportedProtocol>(move(protocol))->supported();
    }

    void async_is_supported_protocol(StringView protocol)
    {
        auto message_buffer = MUST(Messages::RequestServer::IsSupportedProtocol::static_encode(protocol));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<bool> try_is_supported_protocol(ByteString protocol)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::RequestServer::IsSupportedProtocol>(move(protocol)))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    void async_start_request(u64 request_id, StringView method, URL::URL const& url, ReadonlySpan<HTTP::Header> request_headers, ReadonlyBytes request_body, HTTP::CacheMode const& cache_mode, HTTP::Cookie::IncludeCredentials const& include_credentials, Core::ProxyData const& proxy_data)
    {
        auto message_buffer = MUST(Messages::RequestServer::StartRequest::static_encode(request_id, method, move(url), request_headers, request_body, move(cache_mode), move(include_credentials), move(proxy_data)));
        (void)m_connection.post_message(message_buffer);
    }

    bool stop_request(u64 request_id)
    {
        return m_connection.template send_sync<Messages::RequestServer::StopRequest>(request_id)->success();
    }

    void async_stop_request(u64 request_id)
    {
        auto message_buffer = MUST(Messages::RequestServer::StopRequest::static_encode(request_id));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<bool> try_stop_request(u64 request_id)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::RequestServer::StopRequest>(request_id))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    bool set_certificate(u64 request_id, ByteString certificate, ByteString key)
    {
        return m_connection.template send_sync<Messages::RequestServer::SetCertificate>(request_id, move(certificate), move(key))->success();
    }

    void async_set_certificate(u64 request_id, StringView certificate, StringView key)
    {
        auto message_buffer = MUST(Messages::RequestServer::SetCertificate::static_encode(request_id, certificate, key));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<bool> try_set_certificate(u64 request_id, ByteString certificate, ByteString key)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::RequestServer::SetCertificate>(request_id, move(certificate), move(key)))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    void async_ensure_connection(u64 request_id, URL::URL const& url, ::RequestServer::CacheLevel const& cache_level)
    {
        auto message_buffer = MUST(Messages::RequestServer::EnsureConnection::static_encode(request_id, move(url), move(cache_level)));
        (void)m_connection.post_message(message_buffer);
    }

    void async_retrieved_http_cookie(int client_id, u64 request_id, ::RequestServer::RequestType const& request_type, StringView cookie)
    {
        VERIFY(Utf8View { cookie }.validate());
        auto message_buffer = MUST(Messages::RequestServer::RetrievedHttpCookie::static_encode(client_id, request_id, move(request_type), cookie));
        (void)m_connection.post_message(message_buffer);
    }

    void async_retrieved_http_cookie(int client_id, u64 request_id, ::RequestServer::RequestType const& request_type, String const& cookie)
    {
        auto message_buffer = MUST(Messages::RequestServer::RetrievedHttpCookie::static_encode(client_id, request_id, move(request_type), cookie));
        (void)m_connection.post_message(message_buffer);
    }

    void async_estimate_cache_size_accessed_since(u64 cache_size_estimation_id, UnixDateTime const& since)
    {
        auto message_buffer = MUST(Messages::RequestServer::EstimateCacheSizeAccessedSince::static_encode(cache_size_estimation_id, move(since)));
        (void)m_connection.post_message(message_buffer);
    }

    void async_remove_cache_entries_accessed_since(UnixDateTime const& since)
    {
        auto message_buffer = MUST(Messages::RequestServer::RemoveCacheEntriesAccessedSince::static_encode(move(since)));
        (void)m_connection.post_message(message_buffer);
    }

    bool store_cache_associated_data(URL::URL url, ByteString method, Vector<HTTP::Header> request_headers, Optional<u64> vary_key, HTTP::CacheEntryAssociatedData associated_data, Core::AnonymousBuffer data)
    {
        return m_connection.template send_sync<Messages::RequestServer::StoreCacheAssociatedData>(move(url), move(method), move(request_headers), move(vary_key), move(associated_data), move(data))->stored();
    }

    void async_store_cache_associated_data(URL::URL const& url, StringView method, ReadonlySpan<HTTP::Header> request_headers, Optional<u64> const& vary_key, HTTP::CacheEntryAssociatedData const& associated_data, Core::AnonymousBuffer const& data)
    {
        auto message_buffer = MUST(Messages::RequestServer::StoreCacheAssociatedData::static_encode(move(url), method, request_headers, move(vary_key), move(associated_data), move(data)));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<bool> try_store_cache_associated_data(URL::URL url, ByteString method, Vector<HTTP::Header> request_headers, Optional<u64> vary_key, HTTP::CacheEntryAssociatedData associated_data, Core::AnonymousBuffer data)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::RequestServer::StoreCacheAssociatedData>(move(url), move(method), move(request_headers), move(vary_key), move(associated_data), move(data)))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    Optional<Core::AnonymousBuffer> retrieve_cache_associated_data(URL::URL url, ByteString method, Vector<HTTP::Header> request_headers, Optional<u64> vary_key, HTTP::CacheEntryAssociatedData associated_data)
    {
        return m_connection.template send_sync<Messages::RequestServer::RetrieveCacheAssociatedData>(move(url), move(method), move(request_headers), move(vary_key), move(associated_data))->take_data();
    }

    void async_retrieve_cache_associated_data(URL::URL const& url, StringView method, ReadonlySpan<HTTP::Header> request_headers, Optional<u64> const& vary_key, HTTP::CacheEntryAssociatedData const& associated_data)
    {
        auto message_buffer = MUST(Messages::RequestServer::RetrieveCacheAssociatedData::static_encode(move(url), method, request_headers, move(vary_key), move(associated_data)));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<Optional<Core::AnonymousBuffer>> try_retrieve_cache_associated_data(URL::URL url, ByteString method, Vector<HTTP::Header> request_headers, Optional<u64> vary_key, HTTP::CacheEntryAssociatedData associated_data)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::RequestServer::RetrieveCacheAssociatedData>(move(url), move(method), move(request_headers), move(vary_key), move(associated_data)))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

    void async_websocket_connect(u64 websocket_id, URL::URL const& url, StringView origin, ReadonlySpan<ByteString> protocols, ReadonlySpan<ByteString> extensions, ReadonlySpan<HTTP::Header> additional_request_headers)
    {
        auto message_buffer = MUST(Messages::RequestServer::WebsocketConnect::static_encode(websocket_id, move(url), origin, protocols, extensions, additional_request_headers));
        (void)m_connection.post_message(message_buffer);
    }

    void async_websocket_send(u64 websocket_id, bool is_text, ReadonlyBytes data)
    {
        auto message_buffer = MUST(Messages::RequestServer::WebsocketSend::static_encode(websocket_id, is_text, data));
        (void)m_connection.post_message(message_buffer);
    }

    void async_websocket_close(u64 websocket_id, u16 code, StringView reason)
    {
        auto message_buffer = MUST(Messages::RequestServer::WebsocketClose::static_encode(websocket_id, code, reason));
        (void)m_connection.post_message(message_buffer);
    }

    bool websocket_set_certificate(u64 request_id, ByteString certificate, ByteString key)
    {
        return m_connection.template send_sync<Messages::RequestServer::WebsocketSetCertificate>(request_id, move(certificate), move(key))->success();
    }

    void async_websocket_set_certificate(u64 request_id, StringView certificate, StringView key)
    {
        auto message_buffer = MUST(Messages::RequestServer::WebsocketSetCertificate::static_encode(request_id, certificate, key));
        (void)m_connection.post_message(message_buffer);
    }

    IPC::IPCErrorOr<bool> try_websocket_set_certificate(u64 request_id, ByteString certificate, ByteString key)
    {
        if (auto result = m_connection.template send_sync_but_allow_failure<Messages::RequestServer::WebsocketSetCertificate>(request_id, move(certificate), move(key)))
            return move(*result);
        m_connection.shutdown();
        return IPC::ErrorCode::PeerDisconnected;
    }

private:
    IPC::Connection<LocalEndpoint, PeerEndpoint>& m_connection;
};

template<typename LocalEndpoint, typename PeerEndpoint>
class RequestServerProxy;
class RequestServerStub;

class RequestServerEndpoint {
public:
    template<typename LocalEndpoint>
    using Proxy = RequestServerProxy<LocalEndpoint, RequestServerEndpoint>;
    using Stub = RequestServerStub;

    static u32 static_magic() { return 1270977860; }

    static ErrorOr<NonnullOwnPtr<IPC::Message>> decode_message(ReadonlyBytes buffer, [[maybe_unused]] Queue<IPC::Attachment>& attachments)
    {
        FixedMemoryStream stream { buffer };
        auto message_endpoint_magic = TRY(stream.read_value<u32>());

        if (message_endpoint_magic != static_magic())
            return Error::from_string_literal("Endpoint magic number mismatch, not my message!");

        auto message_id = TRY(stream.read_value<i32>());

        switch (message_id) {
        case (int)Messages::RequestServer::MessageID::InitTransport:
            return Messages::RequestServer::InitTransport::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::InitTransportResponse:
            return Messages::RequestServer::InitTransportResponse::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::ConnectNewClient:
            return Messages::RequestServer::ConnectNewClient::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::ConnectNewClientResponse:
            return Messages::RequestServer::ConnectNewClientResponse::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::ConnectNewClients:
            return Messages::RequestServer::ConnectNewClients::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::ConnectNewClientsResponse:
            return Messages::RequestServer::ConnectNewClientsResponse::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::SetDiskCacheSettings:
            return Messages::RequestServer::SetDiskCacheSettings::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::SetDnsServer:
            return Messages::RequestServer::SetDnsServer::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::SetUseSystemDns:
            return Messages::RequestServer::SetUseSystemDns::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::IsSupportedProtocol:
            return Messages::RequestServer::IsSupportedProtocol::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::IsSupportedProtocolResponse:
            return Messages::RequestServer::IsSupportedProtocolResponse::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::StartRequest:
            return Messages::RequestServer::StartRequest::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::StopRequest:
            return Messages::RequestServer::StopRequest::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::StopRequestResponse:
            return Messages::RequestServer::StopRequestResponse::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::SetCertificate:
            return Messages::RequestServer::SetCertificate::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::SetCertificateResponse:
            return Messages::RequestServer::SetCertificateResponse::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::EnsureConnection:
            return Messages::RequestServer::EnsureConnection::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::RetrievedHttpCookie:
            return Messages::RequestServer::RetrievedHttpCookie::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::EstimateCacheSizeAccessedSince:
            return Messages::RequestServer::EstimateCacheSizeAccessedSince::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::RemoveCacheEntriesAccessedSince:
            return Messages::RequestServer::RemoveCacheEntriesAccessedSince::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::StoreCacheAssociatedData:
            return Messages::RequestServer::StoreCacheAssociatedData::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::StoreCacheAssociatedDataResponse:
            return Messages::RequestServer::StoreCacheAssociatedDataResponse::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::RetrieveCacheAssociatedData:
            return Messages::RequestServer::RetrieveCacheAssociatedData::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::RetrieveCacheAssociatedDataResponse:
            return Messages::RequestServer::RetrieveCacheAssociatedDataResponse::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::WebsocketConnect:
            return Messages::RequestServer::WebsocketConnect::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::WebsocketSend:
            return Messages::RequestServer::WebsocketSend::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::WebsocketClose:
            return Messages::RequestServer::WebsocketClose::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::WebsocketSetCertificate:
            return Messages::RequestServer::WebsocketSetCertificate::decode(stream, attachments);
        case (int)Messages::RequestServer::MessageID::WebsocketSetCertificateResponse:
            return Messages::RequestServer::WebsocketSetCertificateResponse::decode(stream, attachments);
        default:
            return Error::from_string_literal("Failed to decode RequestServer message");
        }

        VERIFY_NOT_REACHED();
    }
};

class RequestServerStub : public IPC::Stub {
public:
    RequestServerStub() { }
    virtual ~RequestServerStub() override { }

    virtual u32 magic() const override { return 1270977860; }
    virtual ByteString name() const override { return "RequestServer"; }

    virtual ErrorOr<OwnPtr<IPC::MessageBuffer>> handle(NonnullOwnPtr<IPC::Message> message) override
    {
        switch (message->message_id()) {
        case (int)Messages::RequestServer::MessageID::InitTransport:
            return handle_init_transport(*message);
        case (int)Messages::RequestServer::MessageID::ConnectNewClient:
            return handle_connect_new_client();
        case (int)Messages::RequestServer::MessageID::ConnectNewClients:
            return handle_connect_new_clients(*message);
        case (int)Messages::RequestServer::MessageID::SetDiskCacheSettings:
            return handle_set_disk_cache_settings(*message);
        case (int)Messages::RequestServer::MessageID::SetDnsServer:
            return handle_set_dns_server(*message);
        case (int)Messages::RequestServer::MessageID::SetUseSystemDns:
            return handle_set_use_system_dns();
        case (int)Messages::RequestServer::MessageID::IsSupportedProtocol:
            return handle_is_supported_protocol(*message);
        case (int)Messages::RequestServer::MessageID::StartRequest:
            return handle_start_request(*message);
        case (int)Messages::RequestServer::MessageID::StopRequest:
            return handle_stop_request(*message);
        case (int)Messages::RequestServer::MessageID::SetCertificate:
            return handle_set_certificate(*message);
        case (int)Messages::RequestServer::MessageID::EnsureConnection:
            return handle_ensure_connection(*message);
        case (int)Messages::RequestServer::MessageID::RetrievedHttpCookie:
            return handle_retrieved_http_cookie(*message);
        case (int)Messages::RequestServer::MessageID::EstimateCacheSizeAccessedSince:
            return handle_estimate_cache_size_accessed_since(*message);
        case (int)Messages::RequestServer::MessageID::RemoveCacheEntriesAccessedSince:
            return handle_remove_cache_entries_accessed_since(*message);
        case (int)Messages::RequestServer::MessageID::StoreCacheAssociatedData:
            return handle_store_cache_associated_data(*message);
        case (int)Messages::RequestServer::MessageID::RetrieveCacheAssociatedData:
            return handle_retrieve_cache_associated_data(*message);
        case (int)Messages::RequestServer::MessageID::WebsocketConnect:
            return handle_websocket_connect(*message);
        case (int)Messages::RequestServer::MessageID::WebsocketSend:
            return handle_websocket_send(*message);
        case (int)Messages::RequestServer::MessageID::WebsocketClose:
            return handle_websocket_close(*message);
        case (int)Messages::RequestServer::MessageID::WebsocketSetCertificate:
            return handle_websocket_set_certificate(*message);
        default:
            return Error::from_string_literal("Unknown message ID for RequestServer endpoint");
        }
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_init_transport(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::InitTransport&>(message);
        auto response = init_transport(request.peer_pid());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_connect_new_client()
    {
        auto response = connect_new_client();
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_connect_new_clients(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::ConnectNewClients&>(message);
        auto response = connect_new_clients(request.count());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_set_disk_cache_settings(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::SetDiskCacheSettings&>(message);
        set_disk_cache_settings(request.take_disk_cache_settings());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_set_dns_server(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::SetDnsServer&>(message);
        set_dns_server(request.take_host_or_address(), request.port(), request.use_tls(), request.validate_dnssec_locally());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_set_use_system_dns()
    {
        set_use_system_dns();
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_is_supported_protocol(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::IsSupportedProtocol&>(message);
        auto response = is_supported_protocol(request.take_protocol());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_start_request(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::StartRequest&>(message);
        start_request(request.request_id(), request.take_method(), request.take_url(), request.take_request_headers(), request.take_request_body(), request.take_cache_mode(), request.take_include_credentials(), request.take_proxy_data());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_stop_request(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::StopRequest&>(message);
        auto response = stop_request(request.request_id());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_set_certificate(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::SetCertificate&>(message);
        auto response = set_certificate(request.request_id(), request.take_certificate(), request.take_key());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_ensure_connection(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::EnsureConnection&>(message);
        ensure_connection(request.request_id(), request.take_url(), request.take_cache_level());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_retrieved_http_cookie(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::RetrievedHttpCookie&>(message);
        retrieved_http_cookie(request.client_id(), request.request_id(), request.take_request_type(), request.take_cookie());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_estimate_cache_size_accessed_since(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::EstimateCacheSizeAccessedSince&>(message);
        estimate_cache_size_accessed_since(request.cache_size_estimation_id(), request.take_since());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_remove_cache_entries_accessed_since(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::RemoveCacheEntriesAccessedSince&>(message);
        remove_cache_entries_accessed_since(request.take_since());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_store_cache_associated_data(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::StoreCacheAssociatedData&>(message);
        auto response = store_cache_associated_data(request.take_url(), request.take_method(), request.take_request_headers(), request.take_vary_key(), request.take_associated_data(), request.take_data());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_retrieve_cache_associated_data(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::RetrieveCacheAssociatedData&>(message);
        auto response = retrieve_cache_associated_data(request.take_url(), request.take_method(), request.take_request_headers(), request.take_vary_key(), request.take_associated_data());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_websocket_connect(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::WebsocketConnect&>(message);
        websocket_connect(request.websocket_id(), request.take_url(), request.take_origin(), request.take_protocols(), request.take_extensions(), request.take_additional_request_headers());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_websocket_send(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::WebsocketSend&>(message);
        websocket_send(request.websocket_id(), request.is_text(), request.take_data());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_websocket_close(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::WebsocketClose&>(message);
        websocket_close(request.websocket_id(), request.code(), request.take_reason());
        return nullptr;
    }

    NEVER_INLINE ErrorOr<OwnPtr<IPC::MessageBuffer>> handle_websocket_set_certificate(IPC::Message& message)
    {
        auto& request = static_cast<Messages::RequestServer::WebsocketSetCertificate&>(message);
        auto response = websocket_set_certificate(request.request_id(), request.take_certificate(), request.take_key());
        return make<IPC::MessageBuffer>(TRY(response.encode()));
    }

    virtual Messages::RequestServer::InitTransportResponse init_transport(int peer_pid) = 0;
    virtual Messages::RequestServer::ConnectNewClientResponse connect_new_client() = 0;
    virtual Messages::RequestServer::ConnectNewClientsResponse connect_new_clients(size_t count) = 0;
    virtual void set_disk_cache_settings(HTTP::DiskCacheSettings disk_cache_settings) = 0;
    virtual void set_dns_server(ByteString host_or_address, u16 port, bool use_tls, bool validate_dnssec_locally) = 0;
    virtual void set_use_system_dns() = 0;
    virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(ByteString protocol) = 0;
    virtual void start_request(u64 request_id, ByteString method, URL::URL url, Vector<HTTP::Header> request_headers, ByteBuffer request_body, HTTP::CacheMode cache_mode, HTTP::Cookie::IncludeCredentials include_credentials, Core::ProxyData proxy_data) = 0;
    virtual Messages::RequestServer::StopRequestResponse stop_request(u64 request_id) = 0;
    virtual Messages::RequestServer::SetCertificateResponse set_certificate(u64 request_id, ByteString certificate, ByteString key) = 0;
    virtual void ensure_connection(u64 request_id, URL::URL url, ::RequestServer::CacheLevel cache_level) = 0;
    virtual void retrieved_http_cookie(int client_id, u64 request_id, ::RequestServer::RequestType request_type, String cookie) = 0;
    virtual void estimate_cache_size_accessed_since(u64 cache_size_estimation_id, UnixDateTime since) = 0;
    virtual void remove_cache_entries_accessed_since(UnixDateTime since) = 0;
    virtual Messages::RequestServer::StoreCacheAssociatedDataResponse store_cache_associated_data(URL::URL url, ByteString method, Vector<HTTP::Header> request_headers, Optional<u64> vary_key, HTTP::CacheEntryAssociatedData associated_data, Core::AnonymousBuffer data) = 0;
    virtual Messages::RequestServer::RetrieveCacheAssociatedDataResponse retrieve_cache_associated_data(URL::URL url, ByteString method, Vector<HTTP::Header> request_headers, Optional<u64> vary_key, HTTP::CacheEntryAssociatedData associated_data) = 0;
    virtual void websocket_connect(u64 websocket_id, URL::URL url, ByteString origin, Vector<ByteString> protocols, Vector<ByteString> extensions, Vector<HTTP::Header> additional_request_headers) = 0;
    virtual void websocket_send(u64 websocket_id, bool is_text, ByteBuffer data) = 0;
    virtual void websocket_close(u64 websocket_id, u16 code, ByteString reason) = 0;
    virtual Messages::RequestServer::WebsocketSetCertificateResponse websocket_set_certificate(u64 request_id, ByteString certificate, ByteString key) = 0;
};

#if defined(AK_COMPILER_CLANG)
#pragma clang diagnostic pop
#endif
