mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
fix(libSceRudp): check the context status arguments first and initialization before the id pointer
27 lines
14 KiB
Markdown
27 lines
14 KiB
Markdown
# libSceRudp technical debt
|
|
|
|
### Silent stubs
|
|
|
|
- [sceRudpProcessEvents, sceRudpNetFlush and sceRudpNetReceived](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - there is no reliable-UDP stack on the host, and every `sceRudpWrite`, `sceRudpRead` and `sceRudpGetStatus` call here reports a reset or idle context without queueing data, so no context ever holds pending data to process, send or receive; the three calls return success after `sceRudpInit` and `RUDP_ERROR_NOT_INITIALIZED` before it, as [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/rudp/rudp.cpp) returns OK from its stubs. What the console's `sceRudpNetReceived` returns is unverified. PPSA03490 calls `sceRudpProcessEvents(0)` followed by `sceRudpNetFlush()` from its P2P service thread and ignores the first result.
|
|
- [sceRudpEnableInternalIOThread2](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) takes `(uint32_t stack_size, uint32_t priority, uint64_t affinity)`, taken from the managed `SceRudp.Rudp.EnableInternalIOThread(uint stackSize, uint priority, ulong affinity)` in PPSA06888's Unity metadata; the first two match `sceRudpEnableInternalIOThread`. It returns success after `sceRudpInit` and `RUDP_ERROR_NOT_INITIALIZED` before it, as `sceRudpEnableInternalIOThread` does, without starting any thread. Whether the console reports other errors, and whether it applies the affinity, is unverified.
|
|
- [sceRudpActivate](../../../core/libs/prx/libSceRudp/Export.cpp) takes a context ID, socket address and 32-bit address length. Initialization and initial argument checks match the native implementation; transport mode checks, address conversion and connection activation remain unimplemented and throw.
|
|
|
|
### Unknown function info
|
|
|
|
- [sceRudpGetStatus](../../../core/libs/prx/libSceRudp/Export.cpp) - PPSA01521 passes an output pointer and byte count `0xF8`. Measured on a PS5 (firmware 13.60): the status is 0xF8 bytes; before `sceRudpInit` every call returns `RUDP_ERROR_NOT_INITIALIZED`, and after it a null pointer or a byte count of 0 or above 0xF8 returns `RUDP_ERROR_INVALID_ARGUMENT`. The layout matches `SceRudpStatus` in [Vita3K](https://github.com/AndnixSH/Vita3K-PS-Vita-OS-Fork/blob/master/vita3k/modules/SceRudp/SceLibRudp.cpp) with `currentContexts` at 0x64 and `allocs`, `frees`, `memCurrent` and `memPeak` at 0xC8 to 0xD4. Only `currentContexts` is reported: the traffic counters stay 0 because nothing is sent, and the allocator counters stay 0 because the library does not allocate from the title's pool (the console reports 6 allocations and 0x1260 bytes right after `sceRudpInit`, and 4 more allocations and 0x3F0 bytes per context). The console also writes `currentContexts` and the allocator counters when the byte count is smaller than their offset; only the requested bytes are written here.
|
|
- [sceRudpGetMaxSegmentSize](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - measured on a PS5 (firmware 13.60) in #3073: before `sceRudpInit` it returns `RUDP_ERROR_NOT_INITIALIZED` and leaves the value untouched, also for a null pointer; after it a null pointer returns `RUDP_ERROR_INVALID_ARGUMENT` and a valid one gets 1410 with result 0. No source says whether a size stored by `sceRudpSetMaxSegmentSize` is reported instead, so 1410 is always reported.
|
|
- [sceRudpGetContextStatus](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - `sceRudpGetContextStatus(int ctxId, void* status, size_t size)` returns, after initialization, `0x80770004` for a negative id, a null `status` or a `size` outside 1 to 0x30, before the id lookup (`0x80770003`), as @ntamas94 [read in PS4 firmware 10.71](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6541579780); @BunnyFl's [13.42 run](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6537745577), under an emulator with imports stubbed and not on a console, agrees on size and null. It writes the first `size` bytes of a 0x30-byte block, zero except `0xFFFFFFFF` at bytes 4-7, as it read when idle. A [second run](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6543610064) like it compares `size` as 64 bits (10.71 has `uint32_t`) and reads that block for a bound context and 6 in bytes 0-3 for a listening one, which `main` can't produce.
|
|
- [sceRudpCreateContext](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - checks initialization before its null id pointer, as @BunnyFl's [13.42 run](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6537745577) under an emulator with imports stubbed shows; not measured on a console.
|
|
- [sceRudpSetMaxSegmentSize](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - unverified on a PS5. `(uint16_t mss)` and the checks follow [Vita3K](https://github.com/AndnixSH/Vita3K-PS-Vita-OS-Fork/blob/c86ac732bc811057e690bed280c5076bdf95385e/vita3k/modules/SceRudp/SceLibRudp.cpp#L1573-L1584), with the argument in [RPCS3](https://github.com/RPCS3/rpcs3/blob/8b9ee60569753db8406b66d135cce112156172a1/rpcs3/Emu/Cell/Modules/cellRudp.cpp#L149-L153): `RUDP_ERROR_NOT_INITIALIZED` before `sceRudpInit`, `RUDP_ERROR_NOT_ACCEPTABLE` while a context exists, otherwise stored without a range check and kept across `sceRudpEnd`, as Vita3K keeps it in its library state. Nothing reads the stored size: Vita3K [leaves the getter unimplemented](https://github.com/AndnixSH/Vita3K-PS-Vita-OS-Fork/blob/c86ac732bc811057e690bed280c5076bdf95385e/vita3k/modules/SceRudp/SceLibRudp.cpp#L1080-L1082), so `sceRudpGetMaxSegmentSize` keeps the measured 1410
|
|
- [sceRudpGetOption, sceRudpSetOption](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - full PS5 option contracts are unverified; defaults and validation follow [Vita3K](https://github.com/AndnixSH/Vita3K-PS-Vita-OS-Fork/blob/c86ac732bc811057e690bed280c5076bdf95385e/vita3k/modules/SceRudp/SceLibRudp.cpp). Options 12 and 13 have unknown meanings; last-error option 14 is not maintained. Their setters store all 32 bits per context and return 0 for valid four-byte buffers, preserving acceptance on `main`; their getters throw. Static inspection of PPSA06888 v01.001.008's bundled Unity transport shows its context-set constructor configuring IDs 2, 3, 5 and 6; runtime usage and other paths remain unverified. The plugin wrappers pass four-byte values. No context can connect, so stored settings cannot affect traffic. Closes when: PS5 option contracts are verified and the remaining behavior is implemented.
|
|
- [sceRudpPollCreate, sceRudpPollControl, sceRudpPollWait, sceRudpPollDestroy](../../../core/libs/prx/libSceRudp/Export.cpp) - console hardware behavior and removal of the last entry during an existing wait remain unverified. A [firmware 13.42 report](https://github.com/boykopovar/AnyPS5/pull/10954#issuecomment-6398457761) executes the actual module under emulation with kernel/libc imports stubbed and condition waits scripted, not on console hardware: an empty poll waits for its remaining timeout, including after spurious wakes, and leaves event output untouched. This agrees with the retained wait behavior here and conflicts with the immediate empty return in [Vita3K](https://github.com/AndnixSH/Vita3K-PS-Vita-OS-Fork/blob/c86ac732bc811057e690bed280c5076bdf95385e/vita3k/modules/SceRudp/SceLibRudp.cpp). The argument checks, control operations and 8-byte event layout retain their existing sources; the firmware report has not been independently reproduced here.
|
|
- [sceRudpPollCancel](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - unmeasured: a wait that starts while a cancel is draining. Here the drain waits only for the waits registered when it started; a later wait is neither cancelled nor counted. The rest is measured on a retail PS5 (firmware 13.60) through the real `libSceRudp.sprx` ([@HabibUrRehmanBhattii](https://github.com/boykopovar/AnyPS5/pull/11294#issuecomment-6434977474)), matching @BunnyFl's [13.42 library run](https://github.com/boykopovar/AnyPS5/pull/10954#issuecomment-6399054346): `int sceRudpPollCancel(int pollId)` returns `0x80770001` before `sceRudpInit`, `0x80770004` for a negative id and `0x8077001F` for an unknown one. With no waiter, one cancellation is kept per poll and the next `sceRudpPollWait`, even with a zero timeout, returns `0x80770014` at once. With waiters, all return `0x80770014`, the call returns 0 after they leave, and nothing stays pending.
|
|
- [sceRudpPollDestroy and sceRudpEnd](../../../core/libs/prx/libSceRudp/Export.cpp) - draining remains incomplete. The [detailed firmware 13.42 report](https://github.com/boykopovar/AnyPS5/pull/10954#issuecomment-6399054346) executes the module with emulated/stubbed imports. In the scripted two-waiter Destroy case both waiters return `0x80770014`; Destroy drains them before returning, then destroys the condition variable. A later wait on that destroyed ID returns `0x8077001F`. End similarly drains its active waiter with `0x80770014`; subsequent Wait/Cancel calls return `0x80770001`. Here Destroy/End return without draining and wake existing waiters with `0x8077001F`/`0x80770001`. Real-kernel wake/timeout races, simultaneous control calls, End/re-init overlap and extreme timeout boundaries remain untested; the report is not a console hardware measurement or an independent reproduction here.
|
|
- [sceRudpGetLocalInfo](../../../core/libs/prx/libSceRudp/Export.cpp) - remains a throwing placeholder: on a bound context the console copies the socket's address from `sceNetGetsockname`, which this library does not reach, per @BunnyFl's [13.42 run](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6537745577). Its name and NID are in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceRudp.c).
|
|
- [sceRudpBind](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - follows @BunnyFl's 13.42 [runs](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6537745577) ([records](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6543610064)) under an emulator with imports stubbed, not on a console. `(ctxId, socketId, vport, muxMode)`: after initialization, a negative id or socket (`0x80770004`), a mux mode not 1 or 2 (`0x80770006`), an unknown id (`0x80770003`), a listening context (`0x80770011`) and a second bind (`0x8077001D`), then a mux mode other than its contexts' (`0x80770006`), mux mode 1 with vport 0 (`0x80770015`) and a mux mode 2 vport in use (`0x80770017`). Only mux mode 2 tracks vports. Vport 0 takes the next free one above the last handed out, from 0x2711; the socket's record and counter go when its last context leaves. The disassembly gives 0x2710 after 0xFFFF and `0x80770018` when none is free; not run, so passing 0xFFFF throws.
|
|
- [sceRudpTerminate](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - per the same [run](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6543610064), a bound context that isn't listening frees its vport, and its socket's record if it was the last context, before returning; a listening one is unknown at once but holds both until the next `sceRudpProcessEvents`. Not modelled: the `(2, socketId, 0, 0, 0, 0, arg)` call of the `sceRudpSetEventHandler` handler from the next `sceRudpProcessEvents` after a record goes, since that export takes the four-argument context handler type here; the internal IO thread's steps when a socket's first context binds and when its record goes; and the release deferred for connected contexts, which can't occur here.
|
|
- [sceRudpSetEventHandler](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - returns `0x80770001` before initialization and `0x80770022` for a null handler, and `sceRudpEnd` clears the handler, as the [13.42 run](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6537745577) under an emulator with imports stubbed shows; not measured on a console.
|
|
- [sceRudpListen](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - follows the same [13.42 run](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6537745577), under an emulator with imports stubbed, not on a console. `sceRudpListen(ctxId, backlog)` checks, after initialization, a negative id or a backlog of 0 or less (`0x80770004`), no handler set through `sceRudpSetEventHandler` (`0x80770022`), an unknown id (`0x80770003`), a context not bound with mux mode 2 (`0x80770011`) and a second listen (`0x80770021`), then listens, keeping a backlog of at most 0x80.
|
|
- [sceRudpAccept](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - the success path never ran, since no peer connects: of its arguments the same [13.42 run](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6537745577), under an emulator with imports stubbed and not on a console, ran only `ctxId` and a null `newCtxId`; the types and positions of `handler`, `handlerArg`, `address`, `addressLength` and `vport` come from disassembly. After initialization it checks a negative id or a null `newCtxId` (`0x80770004`), an unknown id (`0x80770003`) and a context that is not listening (`0x80770011`). It then returns `0x80770016` while option 7 is set, as by default, and otherwise waits until `sceRudpTerminate` ends the context and returns `0x80770014`, as the run did. What `sceRudpEnd` does to a waiting accept was not run, so that throws.
|
|
- [sceRudpFlush, sceRudpGetRemoteInfo and sceRudpGetContextBufferStatus](../../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - follow @BunnyFl's [firmware 13.42 run](https://github.com/boykopovar/AnyPS5/issues/13682#issuecomment-6537745577) of the real exports under an emulator with imports stubbed, not a console: `(ctxId)`, `(ctxId, addr, addrLen, vport)` and `(ctxId, void* out, size_t size)`. After the initialization check a negative id returns `INVALID_ARGUMENT`, as do a null output or a size outside 1 to 16 for the buffer status, then an unknown or terminated id `INVALID_CONTEXT_ID`. No context here ever connects, so Flush and GetRemoteInfo then return `NOT_ACCEPTABLE` (0x80770011), as the run gave for created, bound and listening contexts, and the buffer status writes `size` zero bytes and returns 0, as it did for every context state run. The connected states, where the run gave 0 for GetRemoteInfo in states 4 and 5 and for Flush in state 4, are not reachable
|