2024-10-22 18:47:33 -03:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
|
2025-04-06 23:17:36 -03:00
|
|
|
* Copyright (c) 2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
2024-10-22 18:47:33 -03:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2025-04-07 18:41:24 -03:00
|
|
|
#include <AK/Queue.h>
|
2026-06-12 11:17:08 -03:00
|
|
|
#include <AK/SinglyLinkedList.h>
|
|
|
|
|
#include <AK/SinglyLinkedListSizePolicy.h>
|
2025-04-07 23:55:50 -03:00
|
|
|
#include <LibCore/Socket.h>
|
2026-03-13 13:11:22 -03:00
|
|
|
#include <LibIPC/Attachment.h>
|
2025-05-17 10:18:57 -03:00
|
|
|
#include <LibIPC/AutoCloseFileDescriptor.h>
|
2026-06-12 11:17:08 -03:00
|
|
|
#include <LibIPC/Forward.h>
|
2026-06-12 11:30:54 -03:00
|
|
|
#include <LibIPC/ReceivedMessageBytes.h>
|
2026-03-14 13:34:46 -03:00
|
|
|
#include <LibIPC/TransportHandle.h>
|
2025-10-30 09:29:29 -03:00
|
|
|
#include <LibSync/ConditionVariable.h>
|
|
|
|
|
#include <LibSync/Mutex.h>
|
2025-09-17 17:45:03 -03:00
|
|
|
#include <LibThreading/Forward.h>
|
2024-10-22 18:47:33 -03:00
|
|
|
|
|
|
|
|
namespace IPC {
|
|
|
|
|
|
2026-06-12 11:17:08 -03:00
|
|
|
struct SocketMessageHeader {
|
|
|
|
|
enum class Type : u8 {
|
|
|
|
|
Payload = 0,
|
|
|
|
|
FileDescriptorAcknowledgement = 1,
|
|
|
|
|
};
|
|
|
|
|
Type type { Type::Payload };
|
|
|
|
|
u32 payload_size { 0 };
|
|
|
|
|
u32 fd_count { 0 };
|
|
|
|
|
};
|
|
|
|
|
|
2025-04-09 15:54:41 -03:00
|
|
|
class SendQueue : public AtomicRefCounted<SendQueue> {
|
|
|
|
|
public:
|
2026-06-12 11:17:08 -03:00
|
|
|
void enqueue_message(SocketMessageHeader, MessageDataType payload, Vector<int>&& fds);
|
2025-04-09 15:54:41 -03:00
|
|
|
struct BytesAndFds {
|
|
|
|
|
Vector<u8> bytes;
|
|
|
|
|
Vector<int> fds;
|
|
|
|
|
};
|
2025-04-13 22:22:10 -03:00
|
|
|
BytesAndFds peek(size_t max_bytes);
|
|
|
|
|
void discard(size_t bytes_count, size_t fds_count);
|
2025-04-09 15:54:41 -03:00
|
|
|
|
|
|
|
|
private:
|
2026-06-12 11:17:08 -03:00
|
|
|
struct QueuedMessage {
|
|
|
|
|
SocketMessageHeader header;
|
|
|
|
|
MessageDataType payload;
|
|
|
|
|
size_t start_offset { 0 };
|
|
|
|
|
|
|
|
|
|
size_t size() const { return sizeof(SocketMessageHeader) + payload.size(); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
SinglyLinkedList<QueuedMessage, AK::DefaultSizeCalculationPolicy> m_queued_messages;
|
|
|
|
|
size_t m_queued_byte_count { 0 };
|
2025-04-09 15:54:41 -03:00
|
|
|
Vector<int> m_fds;
|
2025-10-30 09:29:29 -03:00
|
|
|
Sync::Mutex m_mutex;
|
2025-04-09 15:54:41 -03:00
|
|
|
};
|
|
|
|
|
|
2024-10-22 18:47:33 -03:00
|
|
|
class TransportSocket {
|
|
|
|
|
AK_MAKE_NONCOPYABLE(TransportSocket);
|
2025-04-08 17:01:46 -03:00
|
|
|
AK_MAKE_NONMOVABLE(TransportSocket);
|
2024-10-22 18:47:33 -03:00
|
|
|
|
|
|
|
|
public:
|
2025-04-02 21:55:11 -03:00
|
|
|
static constexpr socklen_t SOCKET_BUFFER_SIZE = 128 * KiB;
|
|
|
|
|
|
2026-03-11 09:05:09 -03:00
|
|
|
struct Paired {
|
|
|
|
|
NonnullOwnPtr<TransportSocket> local;
|
2026-03-14 13:34:46 -03:00
|
|
|
TransportHandle remote_handle;
|
2026-03-11 09:05:09 -03:00
|
|
|
};
|
|
|
|
|
static ErrorOr<Paired> create_paired();
|
2026-03-19 15:42:05 -03:00
|
|
|
static ErrorOr<NonnullOwnPtr<TransportSocket>> from_socket(NonnullOwnPtr<Core::LocalSocket> socket);
|
2026-03-11 09:05:09 -03:00
|
|
|
|
2024-10-22 18:47:33 -03:00
|
|
|
explicit TransportSocket(NonnullOwnPtr<Core::LocalSocket> socket);
|
|
|
|
|
~TransportSocket();
|
|
|
|
|
|
|
|
|
|
void set_up_read_hook(Function<void()>);
|
|
|
|
|
bool is_open() const;
|
2025-05-20 17:21:17 -03:00
|
|
|
|
2024-10-22 18:47:33 -03:00
|
|
|
void close();
|
2025-05-20 17:21:17 -03:00
|
|
|
void close_after_sending_all_pending_messages();
|
2024-10-22 18:47:33 -03:00
|
|
|
|
|
|
|
|
void wait_until_readable();
|
|
|
|
|
|
2026-06-12 11:17:08 -03:00
|
|
|
void post_message(MessageDataType, Vector<Attachment>& attachments);
|
2024-10-22 18:47:33 -03:00
|
|
|
|
2025-04-06 23:17:36 -03:00
|
|
|
enum class ShouldShutdown {
|
|
|
|
|
No,
|
|
|
|
|
Yes,
|
|
|
|
|
};
|
|
|
|
|
struct Message {
|
2026-06-12 11:30:54 -03:00
|
|
|
ReceivedMessageBytes bytes;
|
2026-03-13 13:11:22 -03:00
|
|
|
Queue<Attachment> attachments;
|
2024-10-22 18:47:33 -03:00
|
|
|
};
|
2025-04-10 15:26:46 -03:00
|
|
|
ShouldShutdown read_as_many_messages_as_possible_without_blocking(Function<void(Message&&)>&&);
|
2024-10-22 18:47:33 -03:00
|
|
|
|
2026-03-14 13:34:46 -03:00
|
|
|
ErrorOr<TransportHandle> release_for_transfer();
|
2024-10-22 18:47:33 -03:00
|
|
|
|
|
|
|
|
private:
|
2025-05-20 17:21:17 -03:00
|
|
|
enum class TransferState {
|
|
|
|
|
Continue,
|
|
|
|
|
SocketClosed,
|
|
|
|
|
};
|
|
|
|
|
[[nodiscard]] TransferState transfer_data(ReadonlyBytes& bytes, Vector<int>& fds);
|
|
|
|
|
|
2025-04-09 15:54:41 -03:00
|
|
|
static ErrorOr<void> send_message(Core::LocalSocket&, ReadonlyBytes& bytes, Vector<int>& unowned_fds);
|
2025-04-06 23:17:36 -03:00
|
|
|
|
2025-10-12 23:58:27 -03:00
|
|
|
enum class IOThreadState {
|
|
|
|
|
Running,
|
|
|
|
|
SendPendingMessagesAndStop,
|
|
|
|
|
Stopped,
|
|
|
|
|
};
|
|
|
|
|
intptr_t io_thread_loop();
|
|
|
|
|
void stop_io_thread(IOThreadState desired_state);
|
|
|
|
|
void wake_io_thread();
|
|
|
|
|
void read_incoming_messages();
|
2026-02-13 02:33:40 -03:00
|
|
|
void notify_read_available();
|
2025-05-20 17:21:17 -03:00
|
|
|
|
2024-10-22 18:47:33 -03:00
|
|
|
NonnullOwnPtr<Core::LocalSocket> m_socket;
|
2025-04-07 18:41:24 -03:00
|
|
|
|
|
|
|
|
// After file descriptor is sent, it is moved to the wait queue until an acknowledgement is received from the peer.
|
|
|
|
|
// This is necessary to handle a specific behavior of the macOS kernel, which may prematurely garbage-collect the file
|
|
|
|
|
// descriptor contained in the message before the peer receives it. https://openradar.me/9477351
|
2025-04-08 17:01:46 -03:00
|
|
|
Queue<NonnullRefPtr<AutoCloseFileDescriptor>> m_fds_retained_until_received_by_peer;
|
2025-10-30 09:29:29 -03:00
|
|
|
Sync::Mutex m_fds_retained_until_received_by_peer_mutex;
|
2025-04-07 23:55:50 -03:00
|
|
|
|
2025-10-12 23:58:27 -03:00
|
|
|
RefPtr<Threading::Thread> m_io_thread;
|
2025-04-07 23:55:50 -03:00
|
|
|
RefPtr<SendQueue> m_send_queue;
|
2025-10-12 23:58:27 -03:00
|
|
|
Atomic<IOThreadState> m_io_thread_state { IOThreadState::Running };
|
2026-04-08 10:49:05 -03:00
|
|
|
Atomic<bool> m_is_being_transferred { false };
|
2025-10-12 23:58:27 -03:00
|
|
|
Atomic<bool> m_peer_eof { false };
|
|
|
|
|
ByteBuffer m_unprocessed_bytes;
|
2026-03-13 13:11:22 -03:00
|
|
|
Queue<Attachment> m_unprocessed_attachments;
|
2025-10-30 09:29:29 -03:00
|
|
|
Sync::Mutex m_incoming_mutex;
|
|
|
|
|
Sync::ConditionVariable m_incoming_cv { m_incoming_mutex };
|
2025-10-12 23:58:27 -03:00
|
|
|
Vector<NonnullOwnPtr<Message>> m_incoming_messages;
|
|
|
|
|
|
|
|
|
|
RefPtr<AutoCloseFileDescriptor> m_wakeup_io_thread_read_fd;
|
|
|
|
|
RefPtr<AutoCloseFileDescriptor> m_wakeup_io_thread_write_fd;
|
|
|
|
|
|
|
|
|
|
RefPtr<AutoCloseFileDescriptor> m_notify_hook_read_fd;
|
|
|
|
|
RefPtr<AutoCloseFileDescriptor> m_notify_hook_write_fd;
|
|
|
|
|
RefPtr<Core::Notifier> m_read_hook_notifier;
|
|
|
|
|
Function<void()> m_on_read_hook;
|
2024-10-22 18:47:33 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|