LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
|
|
|
|
|
* Copyright (c) 2025, stasoid <stasoid@yahoo.com>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <AK/ByteReader.h>
|
2026-01-21 21:51:45 +01:00
|
|
|
#include <AK/Checked.h>
|
2026-03-11 13:05:09 +01:00
|
|
|
#include <AK/ScopeGuard.h>
|
2026-01-21 21:54:20 +01:00
|
|
|
#include <AK/Types.h>
|
2026-03-11 13:05:09 +01:00
|
|
|
#include <LibCore/System.h>
|
2026-03-14 17:34:46 +01:00
|
|
|
#include <LibIPC/File.h>
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
#include <LibIPC/HandleType.h>
|
2026-01-21 22:07:14 +01:00
|
|
|
#include <LibIPC/Limits.h>
|
2026-03-14 17:34:46 +01:00
|
|
|
#include <LibIPC/TransportHandle.h>
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
#include <LibIPC/TransportSocketWindows.h>
|
|
|
|
|
|
|
|
|
|
#include <AK/Windows.h>
|
|
|
|
|
|
|
|
|
|
namespace IPC {
|
|
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
static constexpr size_t MAX_SERIALIZED_ATTACHMENT_SIZE = sizeof(HandleType) + sizeof(WSAPROTOCOL_INFOW);
|
|
|
|
|
static constexpr size_t MAX_ATTACHMENT_DATA_SIZE = MAX_MESSAGE_FD_COUNT * MAX_SERIALIZED_ATTACHMENT_SIZE;
|
|
|
|
|
|
2026-03-19 19:42:05 +01:00
|
|
|
ErrorOr<NonnullOwnPtr<TransportSocketWindows>> TransportSocketWindows::from_socket(NonnullOwnPtr<Core::LocalSocket> socket)
|
|
|
|
|
{
|
|
|
|
|
return make<TransportSocketWindows>(move(socket));
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-11 13:05:09 +01:00
|
|
|
ErrorOr<TransportSocketWindows::Paired> TransportSocketWindows::create_paired()
|
|
|
|
|
{
|
|
|
|
|
int fds[2] {};
|
|
|
|
|
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fds));
|
|
|
|
|
|
|
|
|
|
ArmedScopeGuard guard_fd_0 { [&] { MUST(Core::System::close(fds[0])); } };
|
|
|
|
|
ArmedScopeGuard guard_fd_1 { [&] { MUST(Core::System::close(fds[1])); } };
|
|
|
|
|
|
|
|
|
|
auto socket0 = TRY(Core::LocalSocket::adopt_fd(fds[0]));
|
|
|
|
|
guard_fd_0.disarm();
|
|
|
|
|
TRY(socket0->set_close_on_exec(true));
|
|
|
|
|
TRY(socket0->set_blocking(false));
|
|
|
|
|
|
2026-03-14 17:34:46 +01:00
|
|
|
TRY(Core::System::set_close_on_exec(fds[1], true));
|
2026-03-11 13:05:09 +01:00
|
|
|
guard_fd_1.disarm();
|
|
|
|
|
|
|
|
|
|
return Paired {
|
|
|
|
|
make<TransportSocketWindows>(move(socket0)),
|
2026-03-14 17:34:46 +01:00
|
|
|
TransportHandle { File::adopt_fd(fds[1]) },
|
2026-03-11 13:05:09 +01:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
TransportSocketWindows::TransportSocketWindows(NonnullOwnPtr<Core::LocalSocket> socket)
|
|
|
|
|
: m_socket(move(socket))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TransportSocketWindows::set_peer_pid(int pid)
|
|
|
|
|
{
|
|
|
|
|
m_peer_pid = pid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TransportSocketWindows::set_up_read_hook(Function<void()> hook)
|
|
|
|
|
{
|
|
|
|
|
VERIFY(m_socket->is_open());
|
|
|
|
|
m_socket->on_ready_to_read = move(hook);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TransportSocketWindows::is_open() const
|
|
|
|
|
{
|
|
|
|
|
return m_socket->is_open();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TransportSocketWindows::close()
|
|
|
|
|
{
|
|
|
|
|
m_socket->close();
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-27 22:14:03 -07:00
|
|
|
void TransportSocketWindows::close_after_sending_all_pending_messages()
|
|
|
|
|
{
|
|
|
|
|
close();
|
|
|
|
|
}
|
|
|
|
|
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
void TransportSocketWindows::wait_until_readable()
|
|
|
|
|
{
|
|
|
|
|
auto readable = MUST(m_socket->can_read_without_blocking(-1));
|
|
|
|
|
VERIFY(readable);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
// Maximum size of accumulated unprocessed bytes before we disconnect the peer
|
|
|
|
|
static constexpr size_t MAX_UNPROCESSED_BUFFER_SIZE = 128 * MiB;
|
|
|
|
|
|
|
|
|
|
struct MessageHeader {
|
|
|
|
|
u32 payload_size { 0 };
|
|
|
|
|
u32 attachment_data_size { 0 };
|
|
|
|
|
u32 attachment_count { 0 };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ErrorOr<Vector<u8>> TransportSocketWindows::serialize_attachments(Vector<Attachment>& attachments)
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
{
|
2026-04-07 22:28:49 +02:00
|
|
|
if (attachments.is_empty())
|
|
|
|
|
return Vector<u8> {};
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
VERIFY(m_peer_pid != -1);
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
|
|
|
|
|
HANDLE peer_process_handle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, m_peer_pid);
|
|
|
|
|
if (!peer_process_handle)
|
|
|
|
|
return Error::from_windows_error();
|
2026-04-07 22:28:49 +02:00
|
|
|
ScopeGuard peer_process_guard = [&] { CloseHandle(peer_process_handle); };
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
Vector<u8> serialized_attachments;
|
|
|
|
|
TRY(serialized_attachments.try_ensure_capacity(attachments.size() * MAX_SERIALIZED_ATTACHMENT_SIZE));
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
for (auto& attachment : attachments) {
|
|
|
|
|
int handle = attachment.to_fd();
|
|
|
|
|
ScopeGuard close_original_handle = [&] {
|
|
|
|
|
if (handle != -1)
|
|
|
|
|
(void)Core::System::close(handle);
|
|
|
|
|
};
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
if (Core::System::is_socket(handle)) {
|
|
|
|
|
TRY(serialized_attachments.try_append(to_underlying(HandleType::Socket)));
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
WSAPROTOCOL_INFOW pi {};
|
|
|
|
|
if (WSADuplicateSocketW(handle, m_peer_pid, &pi))
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
return Error::from_windows_error();
|
2026-04-07 22:28:49 +02:00
|
|
|
TRY(serialized_attachments.try_append(reinterpret_cast<u8*>(&pi), sizeof(pi)));
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
} else {
|
2026-04-07 22:28:49 +02:00
|
|
|
TRY(serialized_attachments.try_append(to_underlying(HandleType::Generic)));
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
HANDLE duplicated_handle = INVALID_HANDLE_VALUE;
|
|
|
|
|
if (!DuplicateHandle(GetCurrentProcess(), to_handle(handle), peer_process_handle, &duplicated_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
return Error::from_windows_error();
|
|
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
auto duplicated_fd = to_fd(duplicated_handle);
|
|
|
|
|
TRY(serialized_attachments.try_append(reinterpret_cast<u8*>(&duplicated_fd), sizeof(duplicated_fd)));
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
attachments.clear();
|
|
|
|
|
return serialized_attachments;
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
}
|
|
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
Attachment TransportSocketWindows::deserialize_attachment(ReadonlyBytes& serialized_bytes)
|
|
|
|
|
{
|
|
|
|
|
VERIFY(serialized_bytes.size() >= sizeof(HandleType));
|
2026-01-21 22:00:09 +01:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
UnderlyingType<HandleType> raw_type {};
|
|
|
|
|
ByteReader::load(serialized_bytes.data(), raw_type);
|
|
|
|
|
auto type = static_cast<HandleType>(raw_type);
|
|
|
|
|
serialized_bytes = serialized_bytes.slice(sizeof(HandleType));
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
case HandleType::Generic: {
|
|
|
|
|
VERIFY(serialized_bytes.size() >= sizeof(int));
|
2025-05-17 21:31:11 +05:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
int handle = -1;
|
|
|
|
|
ByteReader::load(serialized_bytes.data(), handle);
|
|
|
|
|
serialized_bytes = serialized_bytes.slice(sizeof(handle));
|
|
|
|
|
return Attachment::from_fd(handle);
|
|
|
|
|
}
|
|
|
|
|
case HandleType::Socket: {
|
|
|
|
|
VERIFY(serialized_bytes.size() >= sizeof(WSAPROTOCOL_INFOW));
|
|
|
|
|
|
|
|
|
|
WSAPROTOCOL_INFOW pi {};
|
|
|
|
|
memcpy(&pi, serialized_bytes.data(), sizeof(pi));
|
|
|
|
|
serialized_bytes = serialized_bytes.slice(sizeof(pi));
|
|
|
|
|
|
|
|
|
|
auto handle = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, &pi, 0, WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
|
|
|
|
|
VERIFY(handle != INVALID_SOCKET);
|
|
|
|
|
return Attachment::from_fd(handle);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TransportSocketWindows::post_message(Vector<u8> const& bytes, Vector<Attachment>& attachments)
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
{
|
2026-04-07 22:28:49 +02:00
|
|
|
VERIFY(bytes.size() <= MAX_MESSAGE_PAYLOAD_SIZE);
|
|
|
|
|
VERIFY(attachments.size() <= MAX_MESSAGE_FD_COUNT);
|
|
|
|
|
|
|
|
|
|
auto attachment_count = attachments.size();
|
|
|
|
|
auto serialized_attachments = MUST(serialize_attachments(attachments));
|
|
|
|
|
VERIFY(serialized_attachments.size() <= MAX_ATTACHMENT_DATA_SIZE);
|
|
|
|
|
|
2025-05-17 21:31:11 +05:00
|
|
|
Vector<u8> message_buffer;
|
2026-04-07 22:28:49 +02:00
|
|
|
MUST(message_buffer.try_resize(sizeof(MessageHeader) + serialized_attachments.size() + bytes.size()));
|
|
|
|
|
|
|
|
|
|
MessageHeader header {
|
|
|
|
|
.payload_size = static_cast<u32>(bytes.size()),
|
|
|
|
|
.attachment_data_size = static_cast<u32>(serialized_attachments.size()),
|
|
|
|
|
.attachment_count = static_cast<u32>(attachment_count),
|
|
|
|
|
};
|
|
|
|
|
memcpy(message_buffer.data(), &header, sizeof(header));
|
|
|
|
|
|
|
|
|
|
auto* serialized_attachment_storage = message_buffer.data() + sizeof(MessageHeader);
|
|
|
|
|
if (!serialized_attachments.is_empty())
|
|
|
|
|
memcpy(serialized_attachment_storage, serialized_attachments.data(), serialized_attachments.size());
|
2025-05-17 21:31:11 +05:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
auto* payload_storage = serialized_attachment_storage + serialized_attachments.size();
|
|
|
|
|
if (!bytes.is_empty())
|
|
|
|
|
memcpy(payload_storage, bytes.data(), bytes.size());
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
|
2026-04-07 22:28:49 +02:00
|
|
|
MUST(transfer(message_buffer.span()));
|
2025-05-17 21:31:11 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ErrorOr<void> TransportSocketWindows::transfer(ReadonlyBytes bytes_to_write)
|
|
|
|
|
{
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
while (!bytes_to_write.is_empty()) {
|
|
|
|
|
|
|
|
|
|
ErrorOr<size_t> maybe_nwritten = m_socket->write_some(bytes_to_write);
|
|
|
|
|
|
|
|
|
|
if (maybe_nwritten.is_error()) {
|
|
|
|
|
auto error = maybe_nwritten.release_error();
|
|
|
|
|
if (error.code() != EWOULDBLOCK)
|
|
|
|
|
return error;
|
|
|
|
|
|
|
|
|
|
struct pollfd pollfd = {
|
|
|
|
|
.fd = static_cast<SOCKET>(m_socket->fd().value()),
|
|
|
|
|
.events = POLLOUT,
|
|
|
|
|
.revents = 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto result = WSAPoll(&pollfd, 1, -1);
|
|
|
|
|
if (result == 1)
|
|
|
|
|
continue;
|
|
|
|
|
if (result == SOCKET_ERROR)
|
|
|
|
|
return Error::from_windows_error();
|
2026-01-21 21:24:14 +01:00
|
|
|
dbgln("TransportSocketWindows::transfer: Unexpected WSAPoll result {}", result);
|
|
|
|
|
return Error::from_string_literal("Unexpected WSAPoll result");
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bytes_to_write = bytes_to_write.slice(maybe_nwritten.value());
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-17 21:31:11 +05:00
|
|
|
TransportSocketWindows::ShouldShutdown TransportSocketWindows::read_as_many_messages_as_possible_without_blocking(Function<void(Message&&)>&& callback)
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
{
|
2025-05-17 21:31:11 +05:00
|
|
|
auto should_shutdown = ShouldShutdown::No;
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
|
|
|
|
|
while (is_open()) {
|
|
|
|
|
|
|
|
|
|
u8 buffer[4096];
|
|
|
|
|
auto maybe_bytes_read = m_socket->read_without_waiting({ buffer, sizeof(buffer) });
|
|
|
|
|
|
|
|
|
|
if (maybe_bytes_read.is_error()) {
|
|
|
|
|
auto error = maybe_bytes_read.release_error();
|
|
|
|
|
if (error.code() == EWOULDBLOCK)
|
|
|
|
|
break;
|
|
|
|
|
if (error.code() == ECONNRESET) {
|
2025-05-17 21:31:11 +05:00
|
|
|
should_shutdown = ShouldShutdown::Yes;
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
break;
|
|
|
|
|
}
|
2026-01-21 21:24:14 +01:00
|
|
|
dbgln("TransportSocketWindows::read_as_many_messages_as_possible_without_blocking: {}", error);
|
|
|
|
|
should_shutdown = ShouldShutdown::Yes;
|
|
|
|
|
break;
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto bytes_read = maybe_bytes_read.release_value();
|
|
|
|
|
if (bytes_read.is_empty()) {
|
2025-05-17 21:31:11 +05:00
|
|
|
should_shutdown = ShouldShutdown::Yes;
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-21 22:00:09 +01:00
|
|
|
if (m_unprocessed_bytes.size() + bytes_read.size() > MAX_UNPROCESSED_BUFFER_SIZE) {
|
|
|
|
|
dbgln("TransportSocketWindows: Unprocessed buffer would exceed {} bytes, disconnecting peer", MAX_UNPROCESSED_BUFFER_SIZE);
|
|
|
|
|
should_shutdown = ShouldShutdown::Yes;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-01-21 21:49:34 +01:00
|
|
|
if (m_unprocessed_bytes.try_append(bytes_read.data(), bytes_read.size()).is_error()) {
|
|
|
|
|
dbgln("TransportSocketWindows: Failed to append to unprocessed_bytes buffer");
|
|
|
|
|
should_shutdown = ShouldShutdown::Yes;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-05-17 21:31:11 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
while (index + sizeof(MessageHeader) <= m_unprocessed_bytes.size()) {
|
|
|
|
|
MessageHeader header;
|
|
|
|
|
memcpy(&header, m_unprocessed_bytes.data() + index, sizeof(MessageHeader));
|
2026-04-07 22:28:49 +02:00
|
|
|
VERIFY(header.payload_size <= MAX_MESSAGE_PAYLOAD_SIZE);
|
|
|
|
|
VERIFY(header.attachment_count <= MAX_MESSAGE_FD_COUNT);
|
|
|
|
|
VERIFY(header.attachment_data_size <= MAX_ATTACHMENT_DATA_SIZE);
|
|
|
|
|
|
|
|
|
|
Checked<size_t> message_size = header.payload_size;
|
|
|
|
|
message_size += header.attachment_data_size;
|
2026-01-21 21:51:45 +01:00
|
|
|
message_size += sizeof(MessageHeader);
|
|
|
|
|
if (message_size.has_overflow() || message_size.value() > m_unprocessed_bytes.size() - index)
|
2025-05-17 21:31:11 +05:00
|
|
|
break;
|
|
|
|
|
Message message;
|
2026-04-07 22:28:49 +02:00
|
|
|
auto attachment_bytes = ReadonlyBytes { m_unprocessed_bytes.data() + index + sizeof(MessageHeader), header.attachment_data_size };
|
|
|
|
|
for (u32 attachment_index = 0; attachment_index < header.attachment_count; ++attachment_index)
|
|
|
|
|
message.attachments.enqueue(deserialize_attachment(attachment_bytes));
|
|
|
|
|
VERIFY(attachment_bytes.is_empty());
|
|
|
|
|
|
|
|
|
|
auto const* payload = m_unprocessed_bytes.data() + index + sizeof(MessageHeader) + header.attachment_data_size;
|
|
|
|
|
if (message.bytes.try_append(payload, header.payload_size).is_error()) {
|
|
|
|
|
dbgln("TransportSocketWindows: Failed to allocate message buffer for payload_size {}", header.payload_size);
|
2026-01-21 21:49:34 +01:00
|
|
|
should_shutdown = ShouldShutdown::Yes;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-05-17 21:31:11 +05:00
|
|
|
callback(move(message));
|
2026-01-21 21:51:45 +01:00
|
|
|
Checked<size_t> new_index = index;
|
2026-04-07 22:28:49 +02:00
|
|
|
new_index += header.payload_size;
|
|
|
|
|
new_index += header.attachment_data_size;
|
2026-01-21 21:51:45 +01:00
|
|
|
new_index += sizeof(MessageHeader);
|
|
|
|
|
if (new_index.has_overflow()) {
|
|
|
|
|
dbgln("TransportSocketWindows: index would overflow");
|
|
|
|
|
should_shutdown = ShouldShutdown::Yes;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
index = new_index.value();
|
2025-05-17 21:31:11 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (index < m_unprocessed_bytes.size()) {
|
2026-01-21 21:49:34 +01:00
|
|
|
auto remaining_bytes_or_error = ByteBuffer::copy(m_unprocessed_bytes.span().slice(index));
|
|
|
|
|
if (remaining_bytes_or_error.is_error()) {
|
|
|
|
|
dbgln("TransportSocketWindows: Failed to copy remaining bytes");
|
|
|
|
|
should_shutdown = ShouldShutdown::Yes;
|
|
|
|
|
} else {
|
|
|
|
|
m_unprocessed_bytes = remaining_bytes_or_error.release_value();
|
|
|
|
|
}
|
2025-05-17 21:31:11 +05:00
|
|
|
} else {
|
|
|
|
|
m_unprocessed_bytes.clear();
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
}
|
|
|
|
|
|
2025-05-17 21:31:11 +05:00
|
|
|
return should_shutdown;
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
}
|
|
|
|
|
|
2026-03-14 17:34:46 +01:00
|
|
|
ErrorOr<TransportHandle> TransportSocketWindows::release_for_transfer()
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
{
|
2026-03-14 17:34:46 +01:00
|
|
|
auto fd = TRY(m_socket->release_fd());
|
|
|
|
|
return TransportHandle { File::adopt_fd(fd) };
|
LibIPC: Port to Windows
The Linux IPC uses SCM_RIGHTS to transfer fds to another process
(see TransportSocket::transfer, which calls LocalSocket::send_message).
File descriptors are handled separately from regular data.
On Windows handles are embedded in regular data. They are duplicated
in the sender process.
Socket handles need special code both on sender side (because they
require using WSADuplicateSocket instead of DuplicateHandle, see
TransportSocketWindows::duplicate_handles) and on receiver side
(because they require WSASocket, see FileWindows.cpp).
TransportSocketWindows::ReadResult::fds vector is always empty, it is
kept the same as Linux version to avoid OS #ifdefs in Connection.h/.cpp
and Web::HTML::MessagePort::read_from_transport. Separate handling of
fds permeates all IPC code, it doesn't make sense to #ifdef out all this
code on Windows. In other words, the Linux code is more generic -
it handles both regular data and fds. On Windows, we need only the
regular data portion of it, and we just use that.
Duplicating handles on Windows requires pid of target (receiver)
process (see TransportSocketWindows::m_peer_pid). This pid is received
during special TransportSocketWindows initialization, which is performed
only on Windows. It is handled in a separate PR #3179.
Note: ChatGPT and [stackoverflow](https://stackoverflow.com/questions/25429887/getting-pid-of-peer-socket-on-windows) suggest using GetExtendedTcpTable/GetTcpTable2
to get peer pid, but this doesn't work because [MIB_TCPROW2::dwOwningPid](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow2)
is "The PID of the process that issued a context bind for this TCP
connection.", so for both ends it will return the pid of the process
that called socketpair.
Co-Authored-By: Andrew Kaster <andrew@ladybird.org>
2025-01-31 10:57:34 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|