diff options
author | Andreas Kling <kling@serenityos.org> | 2022-10-05 13:54:09 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-10-06 09:51:04 +0200 |
commit | ece1b7422fae7ebf82397c71ac32c288db4e099e (patch) | |
tree | b345c0b4528610001c351fde7faf7531678fbb95 | |
parent | 3bb25ef227cf5f9e7421cfc508daccb15be62ffc (diff) | |
download | serenity-ece1b7422fae7ebf82397c71ac32c288db4e099e.zip |
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.
-rw-r--r-- | Userland/Libraries/LibIPC/Connection.cpp | 14 | ||||
-rw-r--r-- | Userland/Libraries/LibIPC/Connection.h | 9 |
2 files changed, 20 insertions, 3 deletions
diff --git a/Userland/Libraries/LibIPC/Connection.cpp b/Userland/Libraries/LibIPC/Connection.cpp index 6c0451788f..3f922d808f 100644 --- a/Userland/Libraries/LibIPC/Connection.cpp +++ b/Userland/Libraries/LibIPC/Connection.cpp @@ -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; } diff --git a/Userland/Libraries/LibIPC/Connection.h b/Userland/Libraries/LibIPC/Connection.h index 60ea681f28..e2a41c0dc6 100644 --- a/Userland/Libraries/LibIPC/Connection.h +++ b/Userland/Libraries/LibIPC/Connection.h @@ -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"); |