1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 13:37:45 +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(); }); 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) ErrorOr<void> ConnectionBase::post_message(Message const& message)
{ {
return post_message(message.encode()); return post_message(message.encode());
@ -38,7 +50,7 @@ ErrorOr<void> ConnectionBase::post_message(MessageBuffer buffer)
#ifdef __serenity__ #ifdef __serenity__
for (auto& fd : buffer.fds) { 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()); shutdown_with_error(result.error());
return result; return result;
} }

View file

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