summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-10-05 13:54:09 +0200
committerAndreas Kling <kling@serenityos.org>2022-10-06 09:51:04 +0200
commitece1b7422fae7ebf82397c71ac32c288db4e099e (patch)
treeb345c0b4528610001c351fde7faf7531678fbb95
parent3bb25ef227cf5f9e7421cfc508daccb15be62ffc (diff)
downloadserenity-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.cpp14
-rw-r--r--Userland/Libraries/LibIPC/Connection.h9
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");