38 Commits
Author SHA1 Message Date
Ondra97 1b182e7fb2 fix(net): keep MSG_DONTWAIT transfers nonblocking on Windows 2026-10-20 21:47:08 +02:00
Alexej Szpevák 92e136a129 feat(libkernel): report the write end of a pipe to equeue descriptor polls
GuestSockets::Ready only knew the read end of a pipe, and WaitAny asked the host for POLLIN on every descriptor that is not a socket, so a write interest on a pipe could never be reported or wake a wait. PipeWriteState gives the free space of the host buffer (F_GETPIPE_SZ less FIONREAD on Linux, the write quota on Windows), EOF once the read end is closed, and whether the host takes a write now; Ready reports the write end when it is writable or at EOF, and WaitAny asks for POLLOUT on it. macOS has no call for the capacity of a pipe and throws.
2026-10-20 13:34:50 +02:00
Adrià f1d13abca4 Merge pull request #7559 from mugurc/fix/libkernel-listening-socket-macos
fix(libkernel): recognize listening sockets on macOS hosts
2026-10-20 12:56:12 +02:00
Alexej Szpevák cb9a4c7417 feat(libkernel): support EV_CLEAR on sockets and pipes in kevent on Linux
kevent threw for EV_CLEAR on a socket or the read end of a pipe; Boost.Asio's kqueue reactor, among others, registers every socket that way. On Linux such a knote now watches its host descriptor through an edge watch. It is armed when added, on every later EV_ADD or EV_ENABLE while enabled, and by each host wakeup; when armed it is checked with the level-triggered readiness test and reported with the current data and EV_EOF, or disarmed if no longer ready, as kqueue_scan re-runs the filter; reporting it disarms it until the next edge. Waits block on the watch's epoll descriptor, so a socket that stays readable does not wake them. Windows and macOS still throw. GuestSockets::NativeDescriptor exposes the host socket behind a guest one for the watch.
2026-10-19 15:05:28 +02:00
Adrià 48f436406b Merge pull request #6663 from karimibrahim07/feat/libkernel-ipv6-v6only
feat(libkernel): set and read IPV6_V6ONLY on a guest socket
2026-10-19 10:44:37 +02:00
mugurc 6f2a61ade0 fix(libkernel): recognize listening sockets on macOS hosts
macOS does not support getsockopt with SO_ACCEPTCONN; it fails with
ENOPROTOOPT. So on macOS the guest's getsockopt of SO_ACCEPTCONN failed,
connect did not see that a stream socket was listening (an address of
another family failed with EAFNOSUPPORT instead of EOPNOTSUPP), and the
read event of a listening socket reported FIONREAD's 0 instead of the
waiting connection and did not ignore its low watermark.

On macOS the listening state is read from the SO_ACCEPTCONN flag of the
socket options that proc_pidfdinfo reports, and the three places that ask
go through NativeListening. Other hosts keep getsockopt.
2026-10-18 16:13:50 +03:00
Dean Galvin 2edaf44a64 Merge main into claude/brave-ride-lz92qi 2026-10-18 17:20:58 +13:00
milescovielloandClaude Opus 5.5 91fbafd94a fix(libkernel): keep refusing a read low-water mark above 1 on non-stream sockets
On Linux, FIONREAD on a datagram socket reports the next datagram only,
where FreeBSD's sbavail counts every queued byte, so a read mark above 1
there could never fire. kevent now throws for it as before; stream
sockets and marks of 1 are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:20:03 +00:00
Claude 9766ea7781 Merge upstream/main into claude/brave-ride-lz92qi
Brings in main's connection verify options, minimum version, ALPN and
certificate readers. The conflicts in libSceSsl/Export.cpp and the
libSceSsl debt entry take the resolution from blawesom's rebase of this
pull request (blawesom/AnyPS5 rebase/6828 at 925c37aa0): SslConnection
keeps main's verifyOptions, minimumVersion and alpn next to the session,
and the debt entries follow main's structure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoU3ZF76A6uR8sCA7NMLch
2026-10-17 11:00:59 +00:00
milescovielloandClaude Opus 5.5 e1d4ccba49 fix(libkernel): take NOTE_LOWAT on socket read and write events
kevent threw for NOTE_LOWAT. On a socket's EVFILT_READ it now sets the
low-water mark as FreeBSD 11's filt_soread does: the event fires once the
buffered bytes reach it, or at end of file or on a listening socket, and
a later change of the knote replaces it. EVFILT_WRITE takes a mark of 1,
where the host's writability stands in for a free byte; other write marks
and marks below 1 still throw. A pipe ignores the mark, as filt_piperead
does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 10:58:41 +00:00
Adrià 8730dde45f Merge pull request #5973 from pipe1os/feat/libkernel-kevent-pipe-read
feat(libkernel): support EVFILT_READ on the read end of a pipe
2026-10-17 06:53:33 +02:00
Claude e37137241d feat(ssl): run TLS 1.2 client connections over Mbed TLS
sceSslConnect performs the client handshake on the host socket that the
guest number maps to in the libkernel or libSceNet socket table, and
sceSslRead and sceSslWrite carry application data. Session state comes
from the context's memory pool, and the server is verified against the
CAs loaded with sceSslLoadCert; a loaded client certificate is sent when
the server asks for one.

libkernel exports KernelLookupSocketNative_nid_no_patch, which checks
its own socket table before the one libSceNet registers. Pools take a
lock so connections can allocate outside the library lock.

TLS 1.3 is compiled out. A missing CA, a verify callback, would-block
sockets and every failure whose console code is unknown throw, as
recorded in the libSceSsl debt entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoU3ZF76A6uR8sCA7NMLch
2026-10-16 11:37:32 +00:00
Felipe Arce 46d49131e7 feat(libkernel): support EVFILT_READ on the read end of a pipe
kevent threw for any descriptor that is not a guest socket. The read end
of a pipe now gets the descriptor knote, following FreeBSD 11's
filt_piperead: data is the number of buffered bytes and EV_EOF is set
once the write end is closed. GuestSockets::Ready falls back to the new
PipeReadState for a descriptor that is not a socket, and WaitAny waits on
the pipe with ppoll on Linux or in 1 ms WSAPoll slices on Windows, only
when the queue holds a pipe. On Windows the equeue waker now starts
Winsock itself, since a queue can wait on a pipe before any socket exists.
2026-10-15 21:56:19 +00:00
Karim Ibrahim 411dc0748f feat(libkernel): set and read IPV6_V6ONLY on a guest socket 2026-10-15 17:48:41 -04:00
RickandClaude Opus 5.5 831c583003 fix(libkernel): refuse a closed loopback TCP port at once on Windows
Windows answers a SYN to a closed port with a RST and then retransmits
the SYN, so connect to a closed loopback port takes about 2 s before
ECONNREFUSED; FreeBSD fails at once. PS5VR (PPSA99177) makes about 33
such connects to 127.0.0.1:17600 and reaches its home screen 45 s late.

When no socket listens on the destination port (GetExtendedTcpTable),
a loopback connect now sets SIO_TCP_INITIAL_RTO with no SYN
retransmissions and fails at once. A port with a listener keeps the
retransmissions: Windows also answers a SYN to a full accept backlog
with a RST, and the retransmission connects once the server accepts,
as the console's does after FreeBSD drops the SYN.

guest_refused_connect requires ECONNREFUSED in under a second for a
closed port through libkernel connect and sceNetConnect, and a second
connect to a listener with backlog 1 to succeed once the server accepts
the first, through both.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 17:04:20 +02:00
Evgeniy KazarinandClaude Opus 5.5 17ded56f12 feat(libkernel): apply SO_RCVTIMEO and SO_SNDTIMEO on a guest socket
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:18:23 +03:00
Evgeniy KazarinandClaude Opus 5.5 7e79f36ed8 feat(libkernel): answer TCP_NODELAY, SO_NOSIGPIPE and SO_NBIO on a guest socket
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:17:26 +03:00
Nicolas FalesyandClaude Opus 5.5 62d8eeae76 fix(libkernel): poll libSceNet sockets with the host wait
With libSceNet sockets on ordinary descriptor numbers (#4391), poll on a
libSceNet socket threw "neither a socket nor a pipe": poll only knew
libkernel sockets and pipes, while select already asks libSceNet through
its poller. libSceNet now lends libkernel the host socket behind a
descriptor, together with an owner that keeps it open, so poll puts it in
the same WSAPoll or poll call as libkernel sockets. ProsperoLight
(PPSA99002) stopped here on Linux and now reaches its PC list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EvDbpwUPTa78oCAJqe7m9K
2026-10-14 19:56:10 +02:00
Nicolas FalesyandClaude Opus 5.5 5dcf28d36c fix(libkernel): answer fcntl status flags on libSceNet sockets
With libSceNet sockets on ordinary descriptor numbers (#4391), a title
that makes a libSceNet socket non-blocking with plain fcntl(F_GETFL) and
fcntl(F_SETFL, O_NONBLOCK) reached File::Fcntl, whose classification
throws for a socket. libSceNet now registers a status control with
libkernel, like its option setter: F_GETFL returns O_RDWR with the
socket's non-blocking flag, F_SETFL sets it through SO_NBIO, as fcntl
already does for libkernel sockets. ProsperoLight (PPSA99002) stopped
here on Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017WeVmjnnPPKdxVTpr2Vjtw
2026-10-14 19:19:54 +02:00
p3nicillinandClaude Opus 5.5 f288daf6fe feat(libkernel): select on pipes on Windows
select now checks pipe descriptors on Windows with the readiness test poll
already uses, so a pipe next to a libSceNet socket no longer throws.
RetroArch (PPSA99169) selects on libmicrohttpd's wake-up pipe beside its
listening socket. guest_select now runs on Windows too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:19:48 +01:00
milescovielloandClaude Opus 5.5 472437a703 fix(libkernel): report socket status from fstat on a guest socket
fstat on a guest socket descriptor passed the guest number to the host,
which has no such descriptor, and threw ("FillFileStat: fstat failed for
fd 268435460"); sceKernelFstat returned EBADF. FreeBSD fills the stat
buffer for a socket through soo_stat (sys/kern/sys_socket.c):

	bzero((caddr_t)ub, sizeof (*ub));
	ub->st_mode = S_IFSOCK;
	...
	if ((sb->sb_state & SBS_CANTRCVMORE) == 0 || sbavail(sb))
		ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
	ub->st_size = sbavail(sb) - sb->sb_ctl;
	...
	if ((sb->sb_state & SBS_CANTSENDMORE) == 0)
		ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;

and pru_sense_null (sys/kern/uipc_socket.c) adds
st_blksize = so->so_snd.sb_hiwat.

fstat and sceKernelFstat now answer a guest socket from the socket
table: S_IFSOCK, the read bits until the receive side is shut down and
drained, the write bits until the send side is shut down, st_size from
the bytes queued and st_blksize from the send buffer size, other fields
zero. shutdown records which side it closed. A closed socket descriptor
returns EBADF. The differences from the console (peer shutdown, the
host's FIONREAD and SO_SNDBUF, socketpair identity) are listed in
TechnicalDebt.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:34:16 +05:30
xXPBSXxandClaude Sonnet 5.5 79e162110a fix(libkernel): report SO_ERROR and the other SOL_SOCKET options like FreeBSD
getsockopt and setsockopt on a libkernel socket knew four SOL_SOCKET options
(SO_REUSEADDR, SO_BROADCAST, SO_SNDBUF, SO_RCVBUF) and failed every other
one with ENOPROTOOPT. The Mound's EOS SDK reads SO_ERROR on two of its
sockets after a connect, which therefore always failed.

The SOL_SOCKET options now follow FreeBSD 11.4 sosetopt and sogetopt:
- SO_ERROR returns the pending error of the socket as a FreeBSD errno and
  reports it once (Winsock does not clear it on read, so the library does).
- SO_TYPE, SO_ACCEPTCONN, SO_KEEPALIVE, SO_DONTROUTE, SO_OOBINLINE and
  SO_LINGER are read from and set on the host socket; the boolean options
  read back as their own bit, as FreeBSD returns so_options & option.
- SO_DEBUG, SO_USELOOPBACK, SO_REUSEPORT, SO_TIMESTAMP and SO_NOSIGPIPE stay
  ENOPROTOOPT until a title needs one.
- A value is read from its first int and fails with EINVAL when shorter, a
  getsockopt buffer is filled up to its length (sooptcopyin, sooptcopyout),
  SO_SNDBUF and SO_RCVBUF below 1 fail with EINVAL, and SO_LINGER outside
  0..65535 seconds fails with EDOM.

A connect on a non-blocking socket now fails with EINPROGRESS on Windows too
(it was EWOULDBLOCK, which a title waiting for the connection does not
expect).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 15:18:29 +02:00
screamm e99816e8f3 fix(libkernel): give guest sockets ordinary descriptor numbers below FD_SETSIZE
libkernel numbered guest sockets from GuestSockets::FirstDescriptor
(0x10000000), so a title that puts a socket in a 1024-bit fd_set writes
fd / 8 bytes past it. The Epic Online Services SDK does this on its
RtcNetworkThread and three titles stop there (#1794):

Palworld PPSA23126 (queeeef, main a11c8f7f7):
  FATAL: unhandled exception 0xc0000005 on thread 37164 'RtcNetworkThread'
    rip 0x00007ffcdb1ea2be eossdk-ps5-shipping.prx.guest.prx+0xdea2be
    rcx 0000000010000005 rsi 0000000000400000 r12 0000000010000005
The Mound PPSA26223 (xXPBSXx, main 0a8b1d32b):
  FATAL: unhandled exception 0xc0000005 on thread 'RtcNetworkThread',
  rip eossdk-ps5-shipping.prx.guest.prx+0xefc6f4, rcx = 0x10000005,
  rsi = 0x400000
Dying Light 2 PPSA02262 (tv7):
  FATAL: unhandled exception 0xc0000005 on thread 'RtcNetworkThread'
    rcx 0000000010000005 ... rsi 0000000000400000 ... r12 0000000010000005

On FreeBSD 11.4 (8c639945) FD_SETSIZE is 1024 (sys/sys/select.h:58-59)
and sockets take the lowest free entry of the one process descriptor
table that files use (kern_descrip.c:1643-1660 fdalloc,
uipc_syscalls.c kern_socket through falloc).

Every socket number is now a real host descriptor: a zero-access NUL
handle registered with _open_osfhandle on Windows (as directory
descriptors already are) and an F_DUPFD_CLOEXEC duplicate of the host
socket on Linux. The socket table maps that number to the socket, so
"is this a socket" is a table lookup instead of a range check at the 31
former FirstDescriptor comparisons. close releases both the socket entry
and the number, dup and dup2 duplicate the number through the host table
and keep the socket shared, dup2 of a file onto a socket number drops the
socket entry, and sceKernelClose now closes sockets too. sceNetSocket and
sceNetAccept take their ids from the same table instead of a counter from
32, so libkernel and libSceNet numbers never collide.

select polls guest sockets alongside libSceNet sockets, the random device,
stdio and (on Linux) host descriptors; poll throws only for an open
descriptor that is not a guest socket and reports POLLNVAL otherwise.
File calls that used to fail with EBADF on the socket range return
FreeBSD's answer for a socket: lseek ESPIPE (kern_lseek), ftruncate and
getdirentries EINVAL (invfo_truncate, getvnode), flock EOPNOTSUPP;
fstat on a socket throws. pread on a closed descriptor returns EBADF.

title failing on host descriptor numbers; these three titles are that
case, and this change keeps host numbering for files and only moves
sockets into it.

Tests: guest_socket_descriptors (new: socket below 1024, select on a
socket and a file together, close frees the number for a file, dup of a
socket, sceKernelClose), guest_select (socket and pipe together, Linux),
guest_poll, guest_dup, guest_socket_pair, guest_fstatfs,
guest_posix_filesystem and guest_sce_net updated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 20378375b31eb5db922db6e55f45e44a4dae6445)
2026-10-13 03:22:36 +00:00
jdmagicandClaude Opus 5.5 d5805fb3e4 fix(libkernel): setsockopt sets options of libSceNet sockets
A title creating a socket with sceNetSocket sets its options with the BSD
setsockopt, which looked the descriptor up only among libkernel's own
sockets and returned EBADF. libSceNet now registers an option setter with
libkernel, as it does for close and select, and accepts SO_REUSEADDR,
SO_BROADCAST, SO_SNDBUF and SO_RCVBUF like libkernel's own sockets.

PPSA01289 (Sackboy: A Big Adventure) sets SO_BROADCAST on its UDP P2P
socket this way in UIpNetDriver::InitBase. The failure made every listen
fail, and the engine travelled back to its default map with ?closed,
reloading it about every two seconds behind the loading screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:23:24 -04:00
jdmagicandClaude Opus 5.5 12b18af550 fix(libkernel): close() closes libSceNet sockets
A libSceNet socket is a kernel descriptor on the console, so titles close it
with close(). libSceNet keeps its sockets in its own table, and libkernel's
close passed their numbers to the CRT, which reported an invalid parameter
and left the socket open. libSceNet now registers a closer with libkernel,
as it registers its poller for select. PPSA01289 (Sackboy: A Big Adventure)
closes its P2P socket this way each time it tears its network session down,
leaking one open socket per attempt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:23:24 -04:00
Hussein Kadhim d694aac7b4 fix(libkernel): translate every host socket error to the guest errno of its name
NativeError listed 17 Winsock and 17 POSIX errors and turned every other
one into EIO. A second connect while the first is pending (WSAEALREADY,
EALREADY) and an option the host rejects (WSAENOPROTOOPT, ENOPROTOOPT)
reached the guest as EIO; on Linux a nonblocking connect (EINPROGRESS),
a send with no destination (EDESTADDRREQ), ENOTSOCK, EAFNOSUPPORT,
EOPNOTSUPP and others did too.

The translation moves to SocketError.hpp and covers the socket errors of
both hosts by name, with the FreeBSD 11 numbers. WSAESHUTDOWN stays EPIPE
as before. socketpair's own table is gone, as NativeError covers it.

(cherry picked from commit a889c98e6a59d62da289f2e6a77355d2b41a1bde)
2026-10-11 23:43:47 +02:00
MarcZX100 e864e687b3 fix(libkernel): saturate oversized select timeouts 2026-10-11 09:16:59 +02:00
MarcZX100 d78af2c710 fix(libkernel): route vector I/O on guest sockets 2026-10-11 01:16:58 +00:00
kjhq 0abe0b832b feat(libkernel): wake socket read and write events instead of polling
A wait on an equeue that holds socket events now blocks in poll/WSAPoll on
those sockets plus a per-thread loopback wake socket, instead of rechecking
every millisecond. Adding, triggering or deleting an event and closing the
equeue wake the blocked waiters. Closing a socket removes its read and write
events, as on FreeBSD. A read event also reports EV_EOF once the peer has
shut down its sending side.
2026-10-11 01:54:15 +02:00
kjhq 9b7535c6a4 feat(libkernel): implement read and write events for guest sockets
sceKernelAddReadEvent/DeleteReadEvent and sceKernelAddWriteEvent/
DeleteWriteEvent register EVFILT_READ and EVFILT_WRITE events on guest
sockets. The equeue polls the host socket for readiness on each wait
and reports the readable byte count or the send buffer size in data,
with EV_EOF on hang-up or error.
2026-10-11 01:54:04 +02:00
Renan Pires fb34636f47 feat(libkernel): implement dup and dup2 2026-10-10 15:52:25 +04:00
Jan ŠléglandClaude Fable 5.1 9d0b105771 fix(libkernel): read and write guest sockets
read, write, _read and _write on a guest socket descriptor went to the
host, which has no such descriptor, so sceKernelRead and sceKernelWrite
threw. They now reach the socket as recv and send without flags, with
the socket layer's errno (EAGAIN 35, EPIPE 32, EBADF 9), a zero-length
read returns 0 as dofileread does, and the two sceKernel forms return
the kernel error for the same cases. The host's SIGPIPE on EPIPE, a
write above INT_MAX bytes, readv, writev and the positioned forms are
recorded in TechnicalDebt.

OpenSSL's QUIC notifier signals its socketpair with write and read.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-09 23:57:33 +02:00
Adrià 3d19932caf Merge pull request #1738 from SleglJan/feat/libkernel-termios
feat(libkernel): implement tcgetattr and tcsetattr
2026-10-09 23:48:53 +02:00
NumberGuan f9be27619e fix(posix): preserve the socket helper during NID patching 2026-10-09 23:19:03 +02:00
Jan ŠléglandClaude Fable 5.1 14cc6497d2 feat(libkernel): implement tcgetattr and tcsetattr
A title's descriptors are taken as never being terminals: a file or
pipe gets ENOTTY with the termios untouched, a socket gets what its
protocol answers a termios ioctl on FreeBSD (EADDRNOTAVAIL for AF_INET,
EOPNOTSUPP otherwise), and a closed or invalid descriptor EBADF.
tcsetattr gives EINVAL for an action other than TCSANOW, TCSADRAIN or
TCSAFLUSH, with or without TCSASOFT, before anything else, and EFAULT
for a null termios before the descriptor is checked; with TCSASOFT a
null termios throws, where FreeBSD's libc faults copying it. What the
console gives a title as descriptors 0 to 2 is unknown, as recorded in
TechnicalDebt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-09 23:17:12 +02:00
Gjon Gojcevic a47fe27d28 feat(libkernel): implement select over libSceNet sockets
libSceNet registers a socket poller with libkernel; select polls the requested descriptors through it until the timeout and rewrites the descriptor sets.
2026-10-07 20:47:03 -04:00
Nahuel Genchi eded1e010f feat(libkernel): implement fchmod and sceKernelFchmod 2026-10-05 20:46:34 -03:00
SamG-Coder 9cbefb7e04 feat(kernel): implement tracked UDP sockets and ioctl 2026-09-25 06:23:44 +10:00