RequestServer: Add IPC to create a new client and return the sockets

We'll need this to implement single-instance RS for the Browser.
This commit is contained in:
Andrew Kaster 2024-04-10 16:02:40 -06:00 committed by Tim Flynn
commit 5e18d157d0
Notes: sideshowbarker 2024-07-16 23:38:54 +09:00
3 changed files with 52 additions and 3 deletions

View file

@ -5,6 +5,7 @@
*/
#include <AK/Badge.h>
#include <AK/IDAllocator.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/RefCounted.h>
#include <AK/Weakable.h>
@ -21,20 +22,65 @@
namespace RequestServer {
static HashMap<int, RefPtr<ConnectionFromClient>> s_connections;
static IDAllocator s_client_ids;
ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket)
: IPC::ConnectionFromClient<RequestClientEndpoint, RequestServerEndpoint>(*this, move(socket), 1)
: IPC::ConnectionFromClient<RequestClientEndpoint, RequestServerEndpoint>(*this, move(socket), s_client_ids.allocate())
{
s_connections.set(1, *this);
s_connections.set(client_id(), *this);
}
void ConnectionFromClient::die()
{
s_connections.remove(client_id());
auto client_id = this->client_id();
s_connections.remove(client_id);
s_client_ids.deallocate(client_id);
if (s_connections.is_empty())
Core::EventLoop::current().quit(0);
}
Messages::RequestServer::ConnectNewClientResponse ConnectionFromClient::connect_new_client()
{
int socket_fds[2] {};
if (auto err = Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds); err.is_error()) {
dbgln("Failed to create client socketpair: {}", err.error());
return { -1, -1 };
}
auto client_socket_or_error = Core::LocalSocket::adopt_fd(socket_fds[0]);
if (client_socket_or_error.is_error()) {
close(socket_fds[0]);
close(socket_fds[1]);
dbgln("Failed to adopt client socket: {}", client_socket_or_error.error());
return { -1, -1 };
}
auto client_socket = client_socket_or_error.release_value();
// Note: A ref is stored in the static s_connections map
auto client = adopt_ref(*new ConnectionFromClient(move(client_socket)));
int fd_passing_socket_fds[2] {};
if (auto err = Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds); err.is_error()) {
close(socket_fds[1]);
dbgln("Failed to create fd-passing socketpair: {}", err.error());
return { -1, -1 };
}
auto fd_passing_socket_or_error = Core::LocalSocket::adopt_fd(fd_passing_socket_fds[0]);
if (fd_passing_socket_or_error.is_error()) {
// socket_fds[0] is already owned by client
close(socket_fds[1]);
close(fd_passing_socket_fds[0]);
close(fd_passing_socket_fds[1]);
dbgln("Failed to adopt fd-passing socket: {}", fd_passing_socket_or_error.error());
return { -1, -1 };
}
auto fd_passing_socket = fd_passing_socket_or_error.release_value();
client->set_fd_passing_socket(move(fd_passing_socket));
return { IPC::File(socket_fds[1], IPC::File::CloseAfterSending), IPC::File(fd_passing_socket_fds[1], IPC::File::CloseAfterSending) };
}
Messages::RequestServer::IsSupportedProtocolResponse ConnectionFromClient::is_supported_protocol(ByteString const& protocol)
{
bool supported = Protocol::find_by_name(protocol.to_lowercase());

View file

@ -32,6 +32,7 @@ public:
private:
explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>);
virtual Messages::RequestServer::ConnectNewClientResponse connect_new_client() override;
virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(ByteString const&) override;
virtual void start_request(i32 request_id, ByteString const&, URL::URL const&, HashMap<ByteString, ByteString> const&, ByteBuffer const&, Core::ProxyData const&) override;
virtual Messages::RequestServer::StopRequestResponse stop_request(i32) override;

View file

@ -3,6 +3,8 @@
endpoint RequestServer
{
connect_new_client() => (IPC::File client_socket, IPC::File client_fd_passing_socket)
// Test if a specific protocol is supported, e.g "http"
is_supported_protocol(ByteString protocol) => (bool supported)