1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 23:28:11 +00:00

LibIPC: Allow giving Connection a separate socket for FD passing

Our IPC protocol currently relies on the behavior of recvfd() and
sendfd() on SerenityOS, which provide an out-of-band queue that can be
accessed independently of the in-band data stream.

To make LibIPC usable on other platforms, this patch adds a mechanism
where IPC::Connection can be given a dedicated socket for FD passing.
This gives us the same behavior as the syscalls on SerenityOS, without
having to change the protocol implementation.
This commit is contained in:
Andreas Kling 2022-10-05 13:54:09 +02:00
parent 3bb25ef227
commit ece1b7422f
2 changed files with 20 additions and 3 deletions

View file

@ -20,6 +20,18 @@ ConnectionBase::ConnectionBase(IPC::Stub& local_stub, NonnullOwnPtr<Core::Stream
m_responsiveness_timer = Core::Timer::create_single_shot(3000, [this] { may_have_become_unresponsive(); });
}
void ConnectionBase::set_fd_passing_socket(NonnullOwnPtr<Core::Stream::LocalSocket> socket)
{
m_fd_passing_socket = move(socket);
}
Core::Stream::LocalSocket& ConnectionBase::fd_passing_socket()
{
if (m_fd_passing_socket)
return *m_fd_passing_socket;
return *m_socket;
}
ErrorOr<void> ConnectionBase::post_message(Message const& message)
{
return post_message(message.encode());
@ -38,7 +50,7 @@ ErrorOr<void> ConnectionBase::post_message(MessageBuffer buffer)
#ifdef __serenity__
for (auto& fd : buffer.fds) {
if (auto result = m_socket->send_fd(fd.value()); result.is_error()) {
if (auto result = fd_passing_socket().send_fd(fd.value()); result.is_error()) {
shutdown_with_error(result.error());
return result;
}

View file

@ -33,6 +33,8 @@ class ConnectionBase : public Core::Object {
public:
virtual ~ConnectionBase() override = default;
void set_fd_passing_socket(NonnullOwnPtr<Core::Stream::LocalSocket>);
bool is_open() const { return m_socket->is_open(); }
ErrorOr<void> post_message(Message const&);
@ -43,6 +45,7 @@ protected:
explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr<Core::Stream::LocalSocket>, u32 local_endpoint_magic);
Core::Stream::LocalSocket& socket() { return *m_socket; }
Core::Stream::LocalSocket& fd_passing_socket();
virtual void may_have_become_unresponsive() { }
virtual void did_become_responsive() { }
@ -60,6 +63,8 @@ protected:
IPC::Stub& m_local_stub;
NonnullOwnPtr<Core::Stream::LocalSocket> m_socket;
OwnPtr<Core::Stream::LocalSocket> m_fd_passing_socket;
RefPtr<Core::Timer> m_responsiveness_timer;
NonnullOwnPtrVector<Message> m_unprocessed_messages;
@ -123,9 +128,9 @@ protected:
break;
index += sizeof(message_size);
auto remaining_bytes = ReadonlyBytes { bytes.data() + index, message_size };
if (auto message = LocalEndpoint::decode_message(remaining_bytes, *m_socket)) {
if (auto message = LocalEndpoint::decode_message(remaining_bytes, fd_passing_socket())) {
m_unprocessed_messages.append(message.release_nonnull());
} else if (auto message = PeerEndpoint::decode_message(remaining_bytes, *m_socket)) {
} else if (auto message = PeerEndpoint::decode_message(remaining_bytes, fd_passing_socket())) {
m_unprocessed_messages.append(message.release_nonnull());
} else {
dbgln("Failed to parse a message");