2024-10-22 15:47:33 -06:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
|
2025-04-07 04:17:36 +02:00
|
|
|
* Copyright (c) 2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
2024-10-22 15:47:33 -06:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2025-04-14 03:22:10 +02:00
|
|
|
#include <AK/MemoryStream.h>
|
2025-04-07 23:41:24 +02:00
|
|
|
#include <AK/Queue.h>
|
2025-04-08 04:55:50 +02:00
|
|
|
#include <LibCore/Socket.h>
|
2025-05-17 18:18:57 +05:00
|
|
|
#include <LibIPC/AutoCloseFileDescriptor.h>
|
2025-05-20 12:31:35 -04:00
|
|
|
#include <LibIPC/File.h>
|
2025-04-08 04:55:50 +02:00
|
|
|
#include <LibThreading/ConditionVariable.h>
|
2025-04-07 23:41:24 +02:00
|
|
|
#include <LibThreading/MutexProtected.h>
|
2025-04-10 22:05:11 +02:00
|
|
|
#include <LibThreading/RWLock.h>
|
2025-04-08 04:55:50 +02:00
|
|
|
#include <LibThreading/Thread.h>
|
2024-10-22 15:47:33 -06:00
|
|
|
|
|
|
|
|
namespace IPC {
|
|
|
|
|
|
2025-04-09 20:54:41 +02:00
|
|
|
class SendQueue : public AtomicRefCounted<SendQueue> {
|
|
|
|
|
public:
|
|
|
|
|
enum class Running {
|
|
|
|
|
No,
|
|
|
|
|
Yes,
|
|
|
|
|
};
|
|
|
|
|
Running block_until_message_enqueued();
|
|
|
|
|
void stop();
|
|
|
|
|
|
|
|
|
|
void enqueue_message(Vector<u8>&& bytes, Vector<int>&& fds);
|
|
|
|
|
struct BytesAndFds {
|
|
|
|
|
Vector<u8> bytes;
|
|
|
|
|
Vector<int> fds;
|
|
|
|
|
};
|
2025-04-14 03:22:10 +02:00
|
|
|
BytesAndFds peek(size_t max_bytes);
|
|
|
|
|
void discard(size_t bytes_count, size_t fds_count);
|
2025-04-09 20:54:41 +02:00
|
|
|
|
|
|
|
|
private:
|
2025-04-14 03:22:10 +02:00
|
|
|
AllocatingMemoryStream m_stream;
|
2025-04-09 20:54:41 +02:00
|
|
|
Vector<int> m_fds;
|
|
|
|
|
Threading::Mutex m_mutex;
|
|
|
|
|
Threading::ConditionVariable m_condition { m_mutex };
|
|
|
|
|
bool m_running { true };
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-22 15:47:33 -06:00
|
|
|
class TransportSocket {
|
|
|
|
|
AK_MAKE_NONCOPYABLE(TransportSocket);
|
2025-04-08 22:01:46 +02:00
|
|
|
AK_MAKE_NONMOVABLE(TransportSocket);
|
2024-10-22 15:47:33 -06:00
|
|
|
|
|
|
|
|
public:
|
2025-04-03 02:55:11 +02:00
|
|
|
static constexpr socklen_t SOCKET_BUFFER_SIZE = 128 * KiB;
|
|
|
|
|
|
2024-10-22 15:47:33 -06:00
|
|
|
explicit TransportSocket(NonnullOwnPtr<Core::LocalSocket> socket);
|
|
|
|
|
~TransportSocket();
|
|
|
|
|
|
|
|
|
|
void set_up_read_hook(Function<void()>);
|
|
|
|
|
bool is_open() const;
|
2025-05-20 16:21:17 -04:00
|
|
|
|
2024-10-22 15:47:33 -06:00
|
|
|
void close();
|
2025-05-20 16:21:17 -04:00
|
|
|
void close_after_sending_all_pending_messages();
|
2024-10-22 15:47:33 -06:00
|
|
|
|
|
|
|
|
void wait_until_readable();
|
|
|
|
|
|
2025-04-08 22:01:46 +02:00
|
|
|
void post_message(Vector<u8> const&, Vector<NonnullRefPtr<AutoCloseFileDescriptor>> const&);
|
2024-10-22 15:47:33 -06:00
|
|
|
|
2025-04-07 04:17:36 +02:00
|
|
|
enum class ShouldShutdown {
|
|
|
|
|
No,
|
|
|
|
|
Yes,
|
|
|
|
|
};
|
|
|
|
|
struct Message {
|
2024-10-22 15:47:33 -06:00
|
|
|
Vector<u8> bytes;
|
2025-04-10 20:26:46 +02:00
|
|
|
Queue<File> fds;
|
2024-10-22 15:47:33 -06:00
|
|
|
};
|
2025-04-10 20:26:46 +02:00
|
|
|
ShouldShutdown read_as_many_messages_as_possible_without_blocking(Function<void(Message&&)>&&);
|
2024-10-22 15:47:33 -06:00
|
|
|
|
|
|
|
|
// Obnoxious name to make it clear that this is a dangerous operation.
|
|
|
|
|
ErrorOr<int> release_underlying_transport_for_transfer();
|
|
|
|
|
|
|
|
|
|
ErrorOr<IPC::File> clone_for_transfer();
|
|
|
|
|
|
|
|
|
|
private:
|
2025-05-20 16:21:17 -04:00
|
|
|
enum class TransferState {
|
|
|
|
|
Continue,
|
|
|
|
|
SocketClosed,
|
|
|
|
|
};
|
|
|
|
|
[[nodiscard]] TransferState transfer_data(ReadonlyBytes& bytes, Vector<int>& fds);
|
|
|
|
|
|
2025-04-09 20:54:41 +02:00
|
|
|
static ErrorOr<void> send_message(Core::LocalSocket&, ReadonlyBytes& bytes, Vector<int>& unowned_fds);
|
2025-04-07 04:17:36 +02:00
|
|
|
|
2025-05-20 16:21:17 -04:00
|
|
|
void stop_send_thread();
|
|
|
|
|
|
2024-10-22 15:47:33 -06:00
|
|
|
NonnullOwnPtr<Core::LocalSocket> m_socket;
|
2025-04-10 22:05:11 +02:00
|
|
|
mutable Threading::RWLock m_socket_rw_lock;
|
2025-04-07 04:17:36 +02:00
|
|
|
ByteBuffer m_unprocessed_bytes;
|
2025-04-10 20:26:46 +02:00
|
|
|
Queue<File> m_unprocessed_fds;
|
2025-04-07 23:41:24 +02: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 22:01:46 +02:00
|
|
|
Queue<NonnullRefPtr<AutoCloseFileDescriptor>> m_fds_retained_until_received_by_peer;
|
2025-04-08 04:55:50 +02:00
|
|
|
|
|
|
|
|
RefPtr<Threading::Thread> m_send_thread;
|
|
|
|
|
RefPtr<SendQueue> m_send_queue;
|
2024-10-22 15:47:33 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|