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
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <AK/NonnullOwnPtr.h>
|
|
|
|
|
#include <LibCore/Socket.h>
|
|
|
|
|
#include <LibCore/System.h>
|
|
|
|
|
#include <LibIPC/TransportSocket.h>
|
2025-09-17 15:45:03 -05:00
|
|
|
#include <LibThreading/Thread.h>
|
2024-10-22 15:47:33 -06:00
|
|
|
|
|
|
|
|
namespace IPC {
|
|
|
|
|
|
2025-04-09 20:54:41 +02:00
|
|
|
void SendQueue::enqueue_message(Vector<u8>&& bytes, Vector<int>&& fds)
|
|
|
|
|
{
|
|
|
|
|
Threading::MutexLocker locker(m_mutex);
|
2025-04-14 03:22:10 +02:00
|
|
|
VERIFY(MUST(m_stream.write_some(bytes.span())) == bytes.size());
|
2025-04-09 20:54:41 +02:00
|
|
|
m_fds.append(fds.data(), fds.size());
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 03:22:10 +02:00
|
|
|
SendQueue::BytesAndFds SendQueue::peek(size_t max_bytes)
|
2025-04-09 20:54:41 +02:00
|
|
|
{
|
|
|
|
|
Threading::MutexLocker locker(m_mutex);
|
2025-04-14 03:22:10 +02:00
|
|
|
BytesAndFds result;
|
|
|
|
|
auto bytes_to_send = min(max_bytes, m_stream.used_buffer_size());
|
|
|
|
|
result.bytes.resize(bytes_to_send);
|
|
|
|
|
m_stream.peek_some(result.bytes);
|
2025-05-24 01:20:35 -06:00
|
|
|
|
|
|
|
|
if (m_fds.size() > 0) {
|
|
|
|
|
auto fds_to_send = min(m_fds.size(), Core::LocalSocket::MAX_TRANSFER_FDS);
|
|
|
|
|
result.fds = Vector<int> { m_fds.span().slice(0, fds_to_send) };
|
|
|
|
|
// NOTE: This relies on a subsequent call to discard to actually remove the fds from m_fds
|
|
|
|
|
}
|
2025-04-14 03:22:10 +02:00
|
|
|
return result;
|
2025-04-09 20:54:41 +02:00
|
|
|
}
|
|
|
|
|
|
2025-04-14 03:22:10 +02:00
|
|
|
void SendQueue::discard(size_t bytes_count, size_t fds_count)
|
2025-04-09 20:54:41 +02:00
|
|
|
{
|
|
|
|
|
Threading::MutexLocker locker(m_mutex);
|
2025-04-14 03:22:10 +02:00
|
|
|
MUST(m_stream.discard(bytes_count));
|
|
|
|
|
m_fds.remove(0, fds_count);
|
2025-04-09 20:54:41 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-22 15:47:33 -06:00
|
|
|
TransportSocket::TransportSocket(NonnullOwnPtr<Core::LocalSocket> socket)
|
|
|
|
|
: m_socket(move(socket))
|
|
|
|
|
{
|
2025-10-13 04:58:27 +02:00
|
|
|
(void)Core::System::setsockopt(m_socket->fd().value(), SOL_SOCKET, SO_SNDBUF, &SOCKET_BUFFER_SIZE, sizeof(SOCKET_BUFFER_SIZE));
|
|
|
|
|
(void)Core::System::setsockopt(m_socket->fd().value(), SOL_SOCKET, SO_RCVBUF, &SOCKET_BUFFER_SIZE, sizeof(SOCKET_BUFFER_SIZE));
|
|
|
|
|
|
2025-04-08 04:55:50 +02:00
|
|
|
m_send_queue = adopt_ref(*new SendQueue);
|
2025-04-09 20:54:41 +02:00
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
{
|
|
|
|
|
auto fds = MUST(Core::System::pipe2(O_CLOEXEC | O_NONBLOCK));
|
|
|
|
|
m_wakeup_io_thread_read_fd = adopt_ref(*new AutoCloseFileDescriptor(fds[0]));
|
|
|
|
|
m_wakeup_io_thread_write_fd = adopt_ref(*new AutoCloseFileDescriptor(fds[1]));
|
|
|
|
|
}
|
2025-04-09 20:54:41 +02:00
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
{
|
|
|
|
|
auto fds = MUST(Core::System::pipe2(O_CLOEXEC | O_NONBLOCK));
|
|
|
|
|
m_notify_hook_read_fd = adopt_ref(*new AutoCloseFileDescriptor(fds[0]));
|
|
|
|
|
m_notify_hook_write_fd = adopt_ref(*new AutoCloseFileDescriptor(fds[1]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_io_thread = Threading::Thread::construct([this] { return io_thread_loop(); });
|
|
|
|
|
m_io_thread->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intptr_t TransportSocket::io_thread_loop()
|
|
|
|
|
{
|
|
|
|
|
Array<struct pollfd, 2> pollfds;
|
|
|
|
|
for (;;) {
|
|
|
|
|
auto want_to_write = [&] {
|
|
|
|
|
auto [bytes, fds] = m_send_queue->peek(1);
|
|
|
|
|
return !bytes.is_empty() || !fds.is_empty();
|
|
|
|
|
}();
|
|
|
|
|
|
|
|
|
|
auto state = m_io_thread_state.load();
|
|
|
|
|
if (state == IOThreadState::Stopped)
|
|
|
|
|
break;
|
|
|
|
|
if (state == IOThreadState::SendPendingMessagesAndStop && !want_to_write) {
|
|
|
|
|
m_io_thread_state = IOThreadState::Stopped;
|
|
|
|
|
break;
|
2025-04-08 04:55:50 +02:00
|
|
|
}
|
2025-05-20 16:21:17 -04:00
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
short events = POLLIN;
|
|
|
|
|
if (want_to_write)
|
|
|
|
|
events |= POLLOUT;
|
|
|
|
|
pollfds[0] = { .fd = m_socket->fd().value(), .events = events, .revents = 0 };
|
|
|
|
|
pollfds[1] = { .fd = m_wakeup_io_thread_read_fd->value(), .events = POLLIN, .revents = 0 };
|
2025-05-20 16:21:17 -04:00
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
ErrorOr<int> result { 0 };
|
|
|
|
|
do {
|
|
|
|
|
result = Core::System::poll(pollfds, -1);
|
|
|
|
|
} while (result.is_error() && result.error().code() == EINTR);
|
|
|
|
|
if (result.is_error()) {
|
|
|
|
|
dbgln("TransportSocket poll error: {}", result.error());
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
2025-04-08 04:55:50 +02:00
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
if (pollfds[1].revents & POLLIN) {
|
|
|
|
|
char buf[64];
|
|
|
|
|
MUST(Core::System::read(m_wakeup_io_thread_read_fd->value(), { buf, sizeof(buf) }));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pollfds[0].revents & POLLIN)
|
|
|
|
|
read_incoming_messages();
|
|
|
|
|
|
|
|
|
|
if (pollfds[0].revents & POLLHUP) {
|
|
|
|
|
m_io_thread_state = IOThreadState::Stopped;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pollfds[0].revents & (POLLERR | POLLNVAL)) {
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pollfds[0].revents & POLLOUT) {
|
|
|
|
|
auto [bytes, fds] = m_send_queue->peek(4096);
|
|
|
|
|
if (!bytes.is_empty() || !fds.is_empty()) {
|
|
|
|
|
ReadonlyBytes remaining = bytes;
|
|
|
|
|
if (transfer_data(remaining, fds) == TransferState::SocketClosed) {
|
|
|
|
|
m_io_thread_state = IOThreadState::Stopped;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VERIFY(m_io_thread_state == IOThreadState::Stopped);
|
|
|
|
|
m_peer_eof = true;
|
|
|
|
|
m_incoming_cv.broadcast();
|
|
|
|
|
return 0;
|
2024-10-22 15:47:33 -06:00
|
|
|
}
|
|
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
void TransportSocket::wake_io_thread()
|
2025-05-20 16:21:17 -04:00
|
|
|
{
|
2025-10-13 04:58:27 +02:00
|
|
|
Array<u8, 1> bytes = { 0 };
|
|
|
|
|
(void)Core::System::write(m_wakeup_io_thread_write_fd->value(), bytes);
|
2025-05-20 16:21:17 -04:00
|
|
|
}
|
|
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
TransportSocket::~TransportSocket()
|
2025-04-08 04:55:50 +02:00
|
|
|
{
|
2025-10-13 04:58:27 +02:00
|
|
|
stop_io_thread(IOThreadState::Stopped);
|
|
|
|
|
m_read_hook_notifier.clear();
|
|
|
|
|
}
|
2025-05-20 16:21:17 -04:00
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
void TransportSocket::stop_io_thread(IOThreadState desired_state)
|
|
|
|
|
{
|
|
|
|
|
VERIFY(desired_state == IOThreadState::Stopped || desired_state == IOThreadState::SendPendingMessagesAndStop);
|
|
|
|
|
m_io_thread_state.store(desired_state, AK::MemoryOrder::memory_order_release);
|
|
|
|
|
wake_io_thread();
|
|
|
|
|
if (m_io_thread && m_io_thread->needs_to_be_joined())
|
|
|
|
|
(void)m_io_thread->join();
|
2025-04-08 04:55:50 +02:00
|
|
|
}
|
2024-10-22 15:47:33 -06:00
|
|
|
|
|
|
|
|
void TransportSocket::set_up_read_hook(Function<void()> hook)
|
|
|
|
|
{
|
2025-10-13 04:58:27 +02:00
|
|
|
m_on_read_hook = move(hook);
|
|
|
|
|
m_read_hook_notifier = Core::Notifier::construct(m_notify_hook_read_fd->value(), Core::NotificationType::Read);
|
|
|
|
|
m_read_hook_notifier->on_activation = [this] {
|
|
|
|
|
VERIFY(m_notify_hook_read_fd);
|
|
|
|
|
char buf[64];
|
|
|
|
|
(void)Core::System::read(m_notify_hook_read_fd->value(), { buf, sizeof(buf) });
|
|
|
|
|
if (m_on_read_hook)
|
|
|
|
|
m_on_read_hook();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Threading::MutexLocker locker(m_incoming_mutex);
|
|
|
|
|
if (!m_incoming_messages.is_empty()) {
|
|
|
|
|
Array<u8, 1> bytes = { 0 };
|
|
|
|
|
MUST(Core::System::write(m_notify_hook_write_fd->value(), bytes));
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-22 15:47:33 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TransportSocket::is_open() const
|
|
|
|
|
{
|
|
|
|
|
return m_socket->is_open();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TransportSocket::close()
|
|
|
|
|
{
|
2025-10-13 04:58:27 +02:00
|
|
|
stop_io_thread(IOThreadState::Stopped);
|
2024-10-22 15:47:33 -06:00
|
|
|
m_socket->close();
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-20 16:21:17 -04:00
|
|
|
void TransportSocket::close_after_sending_all_pending_messages()
|
|
|
|
|
{
|
2025-10-13 04:58:27 +02:00
|
|
|
stop_io_thread(IOThreadState::SendPendingMessagesAndStop);
|
|
|
|
|
m_socket->close();
|
2025-05-20 16:21:17 -04:00
|
|
|
}
|
|
|
|
|
|
2024-10-22 15:47:33 -06:00
|
|
|
void TransportSocket::wait_until_readable()
|
|
|
|
|
{
|
2025-10-13 04:58:27 +02:00
|
|
|
Threading::MutexLocker lock(m_incoming_mutex);
|
|
|
|
|
while (m_incoming_messages.is_empty() && m_io_thread_state == IOThreadState::Running) {
|
|
|
|
|
m_incoming_cv.wait();
|
2024-10-22 15:47:33 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-07 04:17:36 +02:00
|
|
|
struct MessageHeader {
|
2025-04-07 23:41:24 +02:00
|
|
|
enum class Type : u8 {
|
|
|
|
|
Payload = 0,
|
|
|
|
|
FileDescriptorAcknowledgement = 1,
|
|
|
|
|
};
|
|
|
|
|
Type type { Type::Payload };
|
|
|
|
|
u32 payload_size { 0 };
|
2025-04-07 04:17:36 +02:00
|
|
|
u32 fd_count { 0 };
|
2025-05-24 01:19:02 -06:00
|
|
|
|
|
|
|
|
static Vector<u8> encode_with_payload(MessageHeader header, ReadonlyBytes payload)
|
|
|
|
|
{
|
|
|
|
|
Vector<u8> message_buffer;
|
|
|
|
|
message_buffer.resize(sizeof(MessageHeader) + payload.size());
|
|
|
|
|
memcpy(message_buffer.data(), &header, sizeof(MessageHeader));
|
|
|
|
|
memcpy(message_buffer.data() + sizeof(MessageHeader), payload.data(), payload.size());
|
|
|
|
|
return message_buffer;
|
|
|
|
|
}
|
2025-04-07 04:17:36 +02:00
|
|
|
};
|
|
|
|
|
|
2025-04-08 22:01:46 +02:00
|
|
|
void TransportSocket::post_message(Vector<u8> const& bytes_to_write, Vector<NonnullRefPtr<AutoCloseFileDescriptor>> const& fds)
|
2025-04-07 04:17:36 +02:00
|
|
|
{
|
2025-05-24 01:19:02 -06:00
|
|
|
auto num_fds_to_transfer = fds.size();
|
|
|
|
|
|
|
|
|
|
auto message_buffer = MessageHeader::encode_with_payload(
|
|
|
|
|
{
|
|
|
|
|
.type = MessageHeader::Type::Payload,
|
|
|
|
|
.payload_size = static_cast<u32>(bytes_to_write.size()),
|
|
|
|
|
.fd_count = static_cast<u32>(num_fds_to_transfer),
|
|
|
|
|
},
|
|
|
|
|
bytes_to_write);
|
2025-04-08 04:55:50 +02:00
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
{
|
|
|
|
|
Threading::MutexLocker locker(m_fds_retained_until_received_by_peer_mutex);
|
|
|
|
|
for (auto const& fd : fds)
|
|
|
|
|
m_fds_retained_until_received_by_peer.enqueue(fd);
|
|
|
|
|
}
|
2025-04-08 04:55:50 +02:00
|
|
|
|
|
|
|
|
auto raw_fds = Vector<int, 1> {};
|
|
|
|
|
if (num_fds_to_transfer > 0) {
|
|
|
|
|
raw_fds.ensure_capacity(num_fds_to_transfer);
|
2025-05-24 01:19:02 -06:00
|
|
|
for (auto const& owned_fd : fds) {
|
2025-04-08 04:55:50 +02:00
|
|
|
raw_fds.unchecked_append(owned_fd->value());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-09 20:54:41 +02:00
|
|
|
m_send_queue->enqueue_message(move(message_buffer), move(raw_fds));
|
2025-10-13 04:58:27 +02:00
|
|
|
wake_io_thread();
|
2025-04-10 10:16:13 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-09 20:54:41 +02:00
|
|
|
ErrorOr<void> TransportSocket::send_message(Core::LocalSocket& socket, ReadonlyBytes& bytes_to_write, Vector<int>& unowned_fds)
|
2025-04-08 04:55:50 +02:00
|
|
|
{
|
2024-10-22 15:47:33 -06:00
|
|
|
auto num_fds_to_transfer = unowned_fds.size();
|
|
|
|
|
while (!bytes_to_write.is_empty()) {
|
|
|
|
|
ErrorOr<ssize_t> maybe_nwritten = 0;
|
|
|
|
|
if (num_fds_to_transfer > 0) {
|
2025-04-08 04:55:50 +02:00
|
|
|
maybe_nwritten = socket.send_message(bytes_to_write, 0, unowned_fds);
|
2024-10-22 15:47:33 -06:00
|
|
|
} else {
|
2025-04-08 04:55:50 +02:00
|
|
|
maybe_nwritten = socket.write_some(bytes_to_write);
|
2024-10-22 15:47:33 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (maybe_nwritten.is_error()) {
|
2025-04-09 20:54:41 +02:00
|
|
|
if (auto error = maybe_nwritten.release_error(); error.is_errno() && (error.code() == EAGAIN || error.code() == EWOULDBLOCK || error.code() == EINTR)) {
|
|
|
|
|
return {};
|
2024-10-22 15:47:33 -06:00
|
|
|
} else {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bytes_to_write = bytes_to_write.slice(maybe_nwritten.value());
|
2025-04-09 20:54:41 +02:00
|
|
|
num_fds_to_transfer = 0;
|
|
|
|
|
unowned_fds.clear();
|
2024-10-22 15:47:33 -06:00
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-20 16:21:17 -04:00
|
|
|
TransportSocket::TransferState TransportSocket::transfer_data(ReadonlyBytes& bytes, Vector<int>& fds)
|
|
|
|
|
{
|
|
|
|
|
auto byte_count = bytes.size();
|
|
|
|
|
auto fd_count = fds.size();
|
|
|
|
|
|
|
|
|
|
if (auto result = send_message(*m_socket, bytes, fds); result.is_error()) {
|
|
|
|
|
if (result.error().is_errno() && result.error().code() == EPIPE) {
|
|
|
|
|
// The socket is closed from the other end, we can stop sending.
|
|
|
|
|
return TransferState::SocketClosed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbgln("TransportSocket::send_thread: {}", result.error());
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto written_byte_count = byte_count - bytes.size();
|
|
|
|
|
auto written_fd_count = fd_count - fds.size();
|
|
|
|
|
if (written_byte_count > 0 || written_fd_count > 0)
|
|
|
|
|
m_send_queue->discard(written_byte_count, written_fd_count);
|
|
|
|
|
|
|
|
|
|
return TransferState::Continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
void TransportSocket::read_incoming_messages()
|
2024-10-22 15:47:33 -06:00
|
|
|
{
|
2025-10-13 04:58:27 +02:00
|
|
|
Vector<NonnullOwnPtr<Message>> batch;
|
|
|
|
|
while (m_socket->is_open()) {
|
2025-04-07 04:17:36 +02:00
|
|
|
u8 buffer[4096];
|
|
|
|
|
auto received_fds = Vector<int> {};
|
2024-10-22 15:47:33 -06:00
|
|
|
auto maybe_bytes_read = m_socket->receive_message({ buffer, 4096 }, MSG_DONTWAIT, received_fds);
|
|
|
|
|
if (maybe_bytes_read.is_error()) {
|
|
|
|
|
auto error = maybe_bytes_read.release_error();
|
2025-05-10 16:35:59 -04:00
|
|
|
|
|
|
|
|
if (error.is_errno() && error.code() == EAGAIN) {
|
2024-10-22 15:47:33 -06:00
|
|
|
break;
|
|
|
|
|
}
|
2025-05-10 16:35:59 -04:00
|
|
|
if (error.is_errno() && error.code() == ECONNRESET) {
|
2025-10-13 04:58:27 +02:00
|
|
|
m_peer_eof = true;
|
2024-10-22 15:47:33 -06:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbgln("TransportSocket::read_as_much_as_possible_without_blocking: {}", error);
|
|
|
|
|
warnln("TransportSocket::read_as_much_as_possible_without_blocking: {}", error);
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto bytes_read = maybe_bytes_read.release_value();
|
2025-05-24 01:20:35 -06:00
|
|
|
if (bytes_read.is_empty() && received_fds.is_empty()) {
|
2025-10-13 04:58:27 +02:00
|
|
|
m_peer_eof = true;
|
2024-10-22 15:47:33 -06:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-07 04:17:36 +02:00
|
|
|
m_unprocessed_bytes.append(bytes_read.data(), bytes_read.size());
|
|
|
|
|
for (auto const& fd : received_fds) {
|
|
|
|
|
m_unprocessed_fds.enqueue(File::adopt_fd(fd));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-07 23:41:24 +02:00
|
|
|
u32 received_fd_count = 0;
|
|
|
|
|
u32 acknowledged_fd_count = 0;
|
2025-04-07 04:17:36 +02:00
|
|
|
size_t index = 0;
|
2025-04-07 18:22:04 +02:00
|
|
|
while (index + sizeof(MessageHeader) <= m_unprocessed_bytes.size()) {
|
2025-04-07 04:17:36 +02:00
|
|
|
MessageHeader header;
|
|
|
|
|
memcpy(&header, m_unprocessed_bytes.data() + index, sizeof(MessageHeader));
|
2025-04-07 23:41:24 +02:00
|
|
|
if (header.type == MessageHeader::Type::Payload) {
|
|
|
|
|
if (header.payload_size + sizeof(MessageHeader) > m_unprocessed_bytes.size() - index)
|
|
|
|
|
break;
|
|
|
|
|
if (header.fd_count > m_unprocessed_fds.size())
|
|
|
|
|
break;
|
2025-10-13 04:58:27 +02:00
|
|
|
auto message = make<Message>();
|
2025-04-07 23:41:24 +02:00
|
|
|
received_fd_count += header.fd_count;
|
|
|
|
|
for (size_t i = 0; i < header.fd_count; ++i)
|
2025-10-13 04:58:27 +02:00
|
|
|
message->fds.enqueue(m_unprocessed_fds.dequeue());
|
|
|
|
|
message->bytes.append(m_unprocessed_bytes.data() + index + sizeof(MessageHeader), header.payload_size);
|
|
|
|
|
batch.append(move(message));
|
2025-04-07 23:41:24 +02:00
|
|
|
} else if (header.type == MessageHeader::Type::FileDescriptorAcknowledgement) {
|
|
|
|
|
VERIFY(header.payload_size == 0);
|
|
|
|
|
acknowledged_fd_count += header.fd_count;
|
|
|
|
|
} else {
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
index += header.payload_size + sizeof(MessageHeader);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (acknowledged_fd_count > 0) {
|
2025-10-13 04:58:27 +02:00
|
|
|
Threading::MutexLocker locker(m_fds_retained_until_received_by_peer_mutex);
|
2025-04-08 04:55:50 +02:00
|
|
|
while (acknowledged_fd_count > 0) {
|
2025-04-08 22:01:46 +02:00
|
|
|
(void)m_fds_retained_until_received_by_peer.dequeue();
|
2025-04-08 04:55:50 +02:00
|
|
|
--acknowledged_fd_count;
|
|
|
|
|
}
|
2025-04-07 23:41:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (received_fd_count > 0) {
|
2025-04-08 04:55:50 +02:00
|
|
|
Vector<u8> message_buffer;
|
|
|
|
|
message_buffer.resize(sizeof(MessageHeader));
|
2025-04-07 23:41:24 +02:00
|
|
|
MessageHeader header;
|
|
|
|
|
header.payload_size = 0;
|
|
|
|
|
header.fd_count = received_fd_count;
|
|
|
|
|
header.type = MessageHeader::Type::FileDescriptorAcknowledgement;
|
2025-04-08 04:55:50 +02:00
|
|
|
memcpy(message_buffer.data(), &header, sizeof(MessageHeader));
|
2025-04-09 20:54:41 +02:00
|
|
|
m_send_queue->enqueue_message(move(message_buffer), {});
|
2025-10-13 04:58:27 +02:00
|
|
|
wake_io_thread();
|
2025-04-07 04:17:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (index < m_unprocessed_bytes.size()) {
|
|
|
|
|
auto remaining_bytes = MUST(ByteBuffer::copy(m_unprocessed_bytes.span().slice(index)));
|
|
|
|
|
m_unprocessed_bytes = move(remaining_bytes);
|
|
|
|
|
} else {
|
|
|
|
|
m_unprocessed_bytes.clear();
|
2024-10-22 15:47:33 -06:00
|
|
|
}
|
|
|
|
|
|
2025-10-13 04:58:27 +02:00
|
|
|
auto notify_read_available = [&] {
|
|
|
|
|
Array<u8, 1> bytes = { 0 };
|
|
|
|
|
(void)Core::System::write(m_notify_hook_write_fd->value(), bytes);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!batch.is_empty()) {
|
|
|
|
|
Threading::MutexLocker locker(m_incoming_mutex);
|
|
|
|
|
m_incoming_messages.extend(move(batch));
|
|
|
|
|
m_incoming_cv.broadcast();
|
|
|
|
|
notify_read_available();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_peer_eof) {
|
|
|
|
|
m_incoming_cv.broadcast();
|
|
|
|
|
notify_read_available();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TransportSocket::ShouldShutdown TransportSocket::read_as_many_messages_as_possible_without_blocking(Function<void(Message&&)>&& callback)
|
|
|
|
|
{
|
|
|
|
|
Vector<NonnullOwnPtr<Message>> messages;
|
|
|
|
|
{
|
|
|
|
|
Threading::MutexLocker locker(m_incoming_mutex);
|
|
|
|
|
messages = move(m_incoming_messages);
|
|
|
|
|
}
|
|
|
|
|
for (auto& message : messages)
|
|
|
|
|
callback(move(*message));
|
|
|
|
|
return m_peer_eof ? ShouldShutdown::Yes : ShouldShutdown::No;
|
2024-10-22 15:47:33 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ErrorOr<int> TransportSocket::release_underlying_transport_for_transfer()
|
|
|
|
|
{
|
2025-10-13 04:58:27 +02:00
|
|
|
stop_io_thread(IOThreadState::SendPendingMessagesAndStop);
|
2024-10-22 15:47:33 -06:00
|
|
|
return m_socket->release_fd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ErrorOr<IPC::File> TransportSocket::clone_for_transfer()
|
|
|
|
|
{
|
|
|
|
|
return IPC::File::clone_fd(m_socket->fd().value());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|