瀏覽代碼

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.
Andreas Kling 2 年之前
父節點
當前提交
ece1b7422f
共有 2 個文件被更改,包括 20 次插入3 次删除
  1. 13 1
      Userland/Libraries/LibIPC/Connection.cpp
  2. 7 2
      Userland/Libraries/LibIPC/Connection.h

+ 13 - 1
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;
         }

+ 7 - 2
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");